C++11中std::lock_guard的使用

来源:互联网 发布:尚趣玩网络 编辑:程序博客网 时间:2024/06/16 01:57

互斥类的最重要成员函数是lock()和unlock()。在进入临界区时,执行lock()加锁操作,如果这时已经被其它线程锁住,则当前线程在此排队等待。退出临界区时,执行unlock()解锁操作。更好的办法是采用”资源分配时初始化”(RAII)方法来加锁、解锁,这避免了在临界区中因为抛出异常或return等操作导致没有解锁就退出的问题。极大地简化了程序员编写mutex相关的异常处理代码。C++11的标准库中提供了std::lock_guard类模板做mutex的RAII。

std::lock_guard类的构造函数禁用拷贝构造,且禁用移动构造。std::lock_guard类除了构造函数和析构函数外没有其它成员函数

在std::lock_guard对象构造时,传入的mutex对象(即它所管理的mutex对象)会被当前线程锁住。在lock_guard对象被析构时,它所管理的mutex对象会自动解锁,不需要程序员手动调用lock和unlock对mutex进行上锁和解锁操作。lock_guard对象并不负责管理mutex对象的生命周期,lock_guard对象只是简化了mutex对象的上锁和解锁操作,方便线程对互斥量上锁,即在某个lock_guard对象的生命周期内,它所管理的锁对象会一直保持上锁状态;而lock_guard的生命周期结束之后,它所管理的锁对象会被解锁。程序员可以非常方便地使用lock_guard,而不用担心异常安全问题。

std::lock_guard在构造时只被锁定一次,并且在销毁时解锁。

关于std::mutex的基础介绍可以参考: 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(较多开销).

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的测试代码,详细内容介绍可以参考对应的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_guardnamespace {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.phpnamespace {// a global variablestd::list<int> myList;// a global instance of std::mutex to protect global variablestd::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 

原创粉丝点击