C++11中std::lock_guard的使用
互斥類(lèi)的最重要成員函數(shù)是lock()和unlock()。在進(jìn)入臨界區(qū)時(shí),執(zhí)行l(wèi)ock()加鎖操作,如果這時(shí)已經(jīng)被其它線程鎖住,則當(dāng)前線程在此排隊(duì)等待。退出臨界區(qū)時(shí),執(zhí)行unlock()解鎖操作。更好的辦法是采用”資源分配時(shí)初始化”(RAII)方法來(lái)加鎖、解鎖,這避免了在臨界區(qū)中因?yàn)閽伋霎惓;騬eturn等操作導(dǎo)致沒(méi)有解鎖就退出的問(wèn)題。極大地簡(jiǎn)化了程序員編寫(xiě)mutex相關(guān)的異常處理代碼。C++11的標(biāo)準(zhǔn)庫(kù)中提供了std::lock_guard類(lèi)模板做mutex的RAII。
std::lock_guard類(lèi)的構(gòu)造函數(shù)禁用拷貝構(gòu)造,且禁用移動(dòng)構(gòu)造。std::lock_guard類(lèi)除了構(gòu)造函數(shù)和析構(gòu)函數(shù)外沒(méi)有其它成員函數(shù)。
在std::lock_guard對(duì)象構(gòu)造時(shí),傳入的mutex對(duì)象(即它所管理的mutex對(duì)象)會(huì)被當(dāng)前線程鎖住。在lock_guard對(duì)象被析構(gòu)時(shí),它所管理的mutex對(duì)象會(huì)自動(dòng)解鎖,不需要程序員手動(dòng)調(diào)用lock和unlock對(duì)mutex進(jìn)行上鎖和解鎖操作。lock_guard對(duì)象并不負(fù)責(zé)管理mutex對(duì)象的生命周期,lock_guard對(duì)象只是簡(jiǎn)化了mutex對(duì)象的上鎖和解鎖操作,方便線程對(duì)互斥量上鎖,即在某個(gè)lock_guard對(duì)象的生命周期內(nèi),它所管理的鎖對(duì)象會(huì)一直保持上鎖狀態(tài);而lock_guard的生命周期結(jié)束之后,它所管理的鎖對(duì)象會(huì)被解鎖。程序員可以非常方便地使用lock_guard,而不用擔(dān)心異常安全問(wèn)題。
std::lock_guard在構(gòu)造時(shí)只被鎖定一次,并且在銷(xiāo)毀時(shí)解鎖。
關(guān)于std::mutex的基礎(chǔ)介紹可以參考: http://blog.csdn.net/fengbingchun/article/details/73521630?
The difference is that you can lock and unlock a std::unique_lock. std::lock_guard will be locked only once on construction and unlocked on destruction.
std::unique_lock has other features that allow it to e.g.: be constructed without locking the mutex immediately but to build the RAII wrapper. However, std::unique_lock might have a tad more overhead(較多開(kāi)銷(xiāo)).
std::lock_guard also provides a convenient RAII wrapper, but cannot lock multiple mutexes safely. It can be used when you need a wrapper for a limited scope, e.g.: a member function.
One of the differences between std::lock_guard and std::unique_lock is that the programmer is able to unlock std::unique_lock, but she/he is not able to unlock std::lock_guard.
下面是從其他文章中copy的測(cè)試代碼,詳細(xì)內(nèi)容介紹可以參考對(duì)應(yīng)的reference:
#include "lock_guard.hpp"
#include <iostream>
#include <thread>
#include <mutex>
#include <stdexcept>
#include <list>
#include <algorithm>namespace lock_guard_ {///
// reference: http://www.cplusplus.com/reference/mutex/lock_guard/
namespace {
std::mutex mtx;void print_even(int x) {if (x % 2 == 0) std::cout << x << " is even\n";else throw (std::logic_error("not even"));
}void print_thread_id(int id) {try {// using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:std::lock_guard<std::mutex> lck(mtx);print_even(id);} catch (std::logic_error&) {std::cout << "[exception caught]\n";}
}
}int test_lock_guard_1()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(print_thread_id, i + 1);for (auto& th : threads) th.join();return 0;
}///
// reference: http://www.cplusplus.com/reference/mutex/lock_guard/lock_guard/
namespace {
std::mutex mtx2; // mutex for critical sectionvoid print_thread_id2(int id) {mtx2.lock();std::lock_guard<std::mutex> lck(mtx2, std::adopt_lock);std::cout << "thread #" << id << '\n';
}
}int test_lock_guard_2()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(print_thread_id2, i + 1);for (auto& th : threads) th.join();return 0;
}// reference: http://en.cppreference.com/w/cpp/thread/lock_guard
namespace {
int g_i = 0;
std::mutex g_i_mutex; // protects g_ivoid safe_increment()
{std::lock_guard<std::mutex> lock(g_i_mutex);++g_i;std::cout << std::this_thread::get_id() << ": " << g_i << '\n';// g_i_mutex is automatically released when lock goes out of scope
}
}int test_lock_guard_3()
{std::cout << "main: " << g_i << '\n';std::thread t1(safe_increment);std::thread t2(safe_increment);t1.join();t2.join();std::cout << "main: " << g_i << '\n';return 0;
}//
// reference: http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
namespace {
// a global variable
std::list<int> myList;// a global instance of std::mutex to protect global variable
std::mutex myMutex;void addToList(int max, int interval)
{// the access to this function is mutually exclusivestd::lock_guard<std::mutex> guard(myMutex);for (int i = 0; i < max; i++) {if ((i % interval) == 0) myList.push_back(i);}
}void printList()
{// the access to this function is mutually exclusivestd::lock_guard<std::mutex> guard(myMutex);for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr) {std::cout << *itr << ",";}
}
}
int test_lock_guard_4()
{int max = 100;std::thread t1(addToList, max, 1);std::thread t2(addToList, max, 10);std::thread t3(printList);t1.join();t2.join();t3.join();return 0;
}} // namespace lock_guard_
GitHub: https://github.com/fengbingchun/Messy_Test?
總結(jié)
以上是生活随笔為你收集整理的C++11中std::lock_guard的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++11中std::unique_lo
- 下一篇: TEE(Trusted Executio