本文由一个简单的例子详细探讨下死锁是怎么发生的,以及如何避免死锁问题的发生。
死锁是怎么发生的?
死锁比较官方的说法是:是指两个或多个线程在执行过程中,由于争夺资源而造成的一种互相等待的现象,从而导致程序无法继续执行。
上述说可能比较抽象,个人理解当线程1在持有互斥锁A的同时请求互斥锁B,同时线程2持有互斥锁B的同时在请求互斥锁A。即线程1在等待线程2执行完成后将锁B释放,但是线程2在等待线程1执行完后将锁A释放,由此发生了互相等待的情况,即产生了死锁。
代码示例A:
假如我们有2个变量,想使用两个互斥锁分别同步这2个变量的访问。在两个线程中,分别对这两个变量都进行了读或写。如下面代码发生了死锁
#include <iostream>
#include <algorithm>
#include <thread>
#include <mutex>
using namespace std;
std::mutex mtx_a;
std::mutex mtx_b;
int a = 0, b = 0;
// 写入a
void set_a(int tmp)
{
cout << "set_a...1" << endl; //a资源锁定前
std::unique_lock<mutex> lock_a(mtx_a);
cout << "set_a...2" << endl; //a资源已锁定
a = tmp;
this_thread::sleep_for(chrono::seconds(1)); //为了增加触发死锁几率,增加等待,模拟工程中的函数处理需要时间
cout << "set_a...3" << endl; //a资源即将解锁
}
// 写入b
void set_b(int tmp)
{
cout << "set_b...1" << endl; //b资源锁定前
std::unique_lock<mutex> lock_b(mtx_b);
cout << "set_b...1" << endl; //b资源锁定前
b = tmp;
this_thread::sleep_for(chrono::seconds(1)); //为了增加触发