不要被死锁吓死

今天跑步的时候,想起前一阵被问到的死锁问题还没有好好的看过,刚好简书上有一篇比较细致的文章,这里做下总结.

文章链接:

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;   
}

 

posted @ 2020-06-02 23:45  心媛意码  阅读(257)  评论(0编辑  收藏  举报