C++11线程指南(8)--死锁
来源:互联网 发布:国产芯片 知乎 编辑:程序博客网 时间:2024/04/28 22:56
1. 死锁
当多个mutex存在的时候,可能就会产生死锁。避免死锁的一个最通用的方法是,总是按照相同的顺序来锁定两个mutexes, 即总是先于mutex B之前lock mutex A,这样就不会有死锁的可能。有时,这种方法很简单实用,当这些mutexes用于不同的目标。但是,当mutexes用于包含相同类的一个实例时,就不是那么容易了。
例如,如下面程序所示,相同类的两个实例之间交互数据。为了保证数据交互不换并发影响,两个实例都使用mutex进行保护。但是当mutex被嵌套的调用时,就形成了死锁。
然而,C++标准库中的std::lock可以解决死锁,它能同时的lock多个mutex,而不会形成死锁。
#include <mutex>class Dummy {};void swap(Dummy& lhs,Dummy& rhs);class A{private:Dummy myObj;std::mutex mu;public:A(Dummy const& obj):myObj(obj){}friend void swap(A& lhs, A& rhs){ //需要先检测这两个实例是否相同。因为如果在一个已经被获取到的std::mutex上, //试图再次获取锁,这会导致未知的行为。if(&lhs==&rhs) return;// 调用std::lock()来锁定这两个mutexes。std::lock(lhs.mu,rhs.mu);// 构造两个std::lock_guard实例,每个对应一个mutex。std::lock_guard<std::mutex> lock_a(lhs.mu,std::adopt_lock);std::lock_guard<std::mutex> lock_b(rhs.mu,std::adopt_lock);swap(lhs.myObj, rhs.myObj);}};swap函数开始会检测参数是否相同,因为重复去lock一个已经被锁定了的std::mutex会导致未知行为。如果需要支持重复的lock, 可以采用std::recursive_mutex。
然后,调用std::lock()来锁定两个mutexes,接着构造了两个std::lock_guard实例。
参数std::adopt_lock用来告诉std::lock_guard,传入的mutex已经被lock了,它们仅能拥有mutex上面已经存在的锁的使用权,而不能在构造函数中再次lock the mutex.
这就确保了mutexes在函数退出时,或抛出异常时,能被准确的unlock. 另外,如果std::lock成功地在一个mutex上lock, 但是lock另一个mutex时抛出了异常,前一个被锁的mutex会被自动释放。std::lock提供了all-or-nothing机制。
尽管std::lock能帮组我们需要一起获取多个mutex时,避免死锁。但是,分别获取多个mutex时,却无能为力。这种情况下,就需要开发人员自己来避免出现死锁了。这不是容易的事情,因为死锁是多线程代码中最可能出现的问题。不过,还是存在一些规则来避免死锁。
2. 避免死锁
尽管锁是出现在死锁中的最常见的要素,但是死锁并不只是会占用锁。我们可以在两个线程之间,不使用锁来创建一个死锁,例如,两个std:thread object相互调用join()。这个简单的死循环可以发生在任何地方,如果一个线程等待另一个线程执行,而另一个线程又在等待这个线程。除了两个线程,多个线程之间同样也可能出现死锁。
一个原则是,如果另外一个线程可能会依赖当前线程,则不要再让当前线程依赖那个线程了。
0 0
- C++11线程指南(8)--死锁
- 8 线程、死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程-死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 线程死锁
- 5.5-两个二进制间转换的步数
- 【android】禁止Edittext弹出软键盘并且使光标正常显示
- ZOJ - 1093 Monkey and Banana
- IOS基础_Block语法的简单使用
- krpano 教程 - bing地图插件的应用
- C++11线程指南(8)--死锁
- 光子嫩肤治疗脸色蜡黄有什么优势
- Java设计模式--Facade外观模式
- 二十四:微信公众帐号开发-自定义菜单的创建及菜单事件响应
- VC6 在win7下无法兼容office2010问题解决 FileTool.dll
- LeetCode——Rotate Image
- 数制转换(栈的应用)
- java 在acm中的使用
- springmvc 发送ajax中文乱码的几种解决办法