C++11多线程编程(三)——lock_guard和unique_lock

若是熟悉C++多线程的童鞋可能有了解到实现的互斥锁的机制还有这个写法ios

lock_guard<mutex> guard(mt);

那么这句话是什么意思呢?为何又要搞个这样的写法呢?多线程

这个也是构造互斥锁的写法,就是会在lock_guard构造函数里加锁,在析构函数里解锁,之因此搞了这个写法,C++委员会的解释是防止使用mutex加锁解锁的时候,忘记解锁unlock了。函数

#include <iostream> #include <thread> #include <string> #include <mutex>
using namespace std; mutex mt; void thread_task() { for (int i = 0; i < 10; i++) { lock_guard<mutex> guard(mt); cout << "print thread: " << i << endl; } } int main() { thread t(thread_task); for (int i = 0; i > -10; i--) { lock_guard<mutex> guard(mt); cout << "print main: " << i << endl; } t.join(); return 0; }

这里说析构函数里解锁,那么到底何时调用析构函数呢?构造函数加锁咱们好理解,写下这个语句的时候调用lock_guard<mutex> guard(mt),那么调用析构函数应该是大括号{}结束的时候,也就是说定义lock_guard的时候调用构造函数加锁,大括号解锁的时候调用析构函数解锁。学习

虽然lock_guard挺好用的,可是有个很大的缺陷,在定义lock_guard的地方会调用构造函数加锁,在离开定义域的话lock_guard就会被销毁,调用析构函数解锁。这就产生了一个问题,若是这个定义域范围很大的话,那么锁的粒度就很大,很大程序上会影响效率。spa

因此为了解决lock_guard锁的粒度过大的缘由,unique_lock就出现了。线程

unique_lock<mutex> unique(mt);调试

这个会在构造函数加锁,而后能够利用unique.unlock()来解锁,因此当你以为锁的粒度太多的时候,能够利用这个来解锁,而析构的时候会判断当前锁的状态来决定是否解锁,若是当前状态已是解锁状态了,那么就不会再次解锁,而若是当前状态是加锁状态,就会自动调用unique.unlock()来解锁。而lock_guard在析构的时候必定会解锁,也没有中途解锁的功能。code

固然,方便确定是有代价的,unique_lock内部会维护一个锁的状态,因此在效率上确定会比lock_guard慢。blog

因此,以上两种加锁解锁的方法,加上前面文章介绍的mutex方法,具体该使用哪个,要依照具体的业务需求来决定,固然mt.lock()和mt.unlock()无论是哪一种状况,是确定均可以使用的。string

对我而言,总感受这个lock_guard有点鸡肋而已,彻底能够用mutex来替代,忘记解锁的话通常均可以经过调试发现,并且通常状况下都不会忘记。仅仅只是由于怕忘记解锁这个缘由的话,真的感受有点画蛇添足,徒增学习成本罢了。

固然也许C++委员会有他们本身的考虑,对于咱们而言,也只能记住就是了。

更多精彩内容,请关注同名公众:一点笔记alittle

相关文章
相关标签/搜索