今天跑步的时候,想起前一阵被问到的死锁问题还没有好好的看过,刚好简书上有一篇比较细致的文章,这里做下总结.
文章链接:
https://www.jianshu.com/p/cab2fbc4b794
总结:
1.这里死锁产生的原因,线程t1等待t2释放mtB,而线程t2等待t1释放mtA.
2.死锁解决的办法:让这两个互斥量同时上锁,然后通过adopt_lock参数来在后面能够正确释放.
ps:一个官方的例子
:https://zh.cppreference.com/w/cpp/thread/lock_tag
//为什么需要采用两个互斥量,不可以使用一个互斥量,然后在函数最开始进行加锁,然后在函数结束时进行解锁码??
#include <mutex>
#include <thread>
#include<iostream>
using namespace std; struct bank_account {explicit bank_account(int balance) : balance(balance) {}int balance;std::mutex m;
};void transfer(bank_account &from, bank_account &to, int amount)
{// 锁定两个互斥而不死锁std::lock(from.m, to.m);// 保证二个已锁定互斥在作用域结尾解锁std::lock_guard<std::mutex> lock1(from.m, std::adopt_lock);std::lock_guard<std::mutex> lock2(to.m, std::adopt_lock);// 等价方法:
// std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
// std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
// std::lock(lock1, lock2);from.balance -= amount;to.balance += amount;
}int main()
{bank_account my_account(100);bank_account your_account(50);std::thread t1(transfer, std::ref(my_account), std::ref(your_account), 10);std::thread t2(transfer, std::ref(your_account), std::ref(my_account), 5);t1.join();t2.join();cout << "my_account:" << my_account.balance << endl;cout << "your_account:" << your_account.balance << endl;
}