C++并发与多线程(10) | 死锁

一、死锁概念 

只有两个互斥量才会产生死锁问题。

    举个例子:

    两个锁——金锁,银锁和两个线程A,B

    (1)A执行时,这个线程先锁金锁,把金锁Lock()成功了,然后它去lock银锁。

    出现了上下文切换

    (2)B执行了,这个线程先锁银锁,因为银锁还没有被锁,所以银锁lock()成功了,B然后就去lock金锁。

此时,死锁就产生了,两个线程互相锁住。

    (3)A因为拿不到银锁头,流程走不下去;

    (4)B因为拿不到金锁头,流程也走不下去。

这个A因为拿不到银锁头,流程走不下去,是不是意思是因为银锁被B锁定了,所以这个A里面去lock银锁的代码运行不下去,被卡着不动!

在这个情况下,线程 A 因为无法获得银锁而被阻塞,因为银锁已经被线程 B 锁定了。线程 B 也因为无法获得金锁而被阻塞,因为金锁已经被线程 A 锁定了。这两个线程互相等待对方释放它们需要的锁,形成了死锁。

这是一个经典的死锁情况,通常需要使用一些方法来解决,例如确保所有线程以相同的顺序获取锁,或使用超时机制来防止死锁。在多线程编程中,避免死锁是一个重要的问题,需要仔细规划和管理线程之间的资源争用。

二、死锁演示

示例,创建了两个Mutex:


#include 
#include 
#include 
#include 
#include 
using namespace std;

class A {
public:
    // 收集数据的函数
    void inMsgRecvQueue()
    {
        for (int i = 0; i < 100000; ++i)
        {
            cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
            my_mutex1.lock();
            my_mutex2.lock();

            msgRecvQueue.push_back(i);

            my_mutex2.unlock();
            my_mutex1.unlock();
        }
        return;
    }
    bool outMsgLULPro(int& command)
    {
        //std::lock_guard sbguard(my_mutex); // 
        my_mutex2.lock();
        my_mutex1.lock();
        if (!msgRecvQueue.empty())
        {
            // 取数据 & 去除这个数据
            command = msgRecvQueue.front();
            msgRecvQueue.pop_front();
            my_mutex1.unlock();
            my_mutex2.unlock();

            return true;
        }
        my_mutex1.unlock();
        my_mutex2.unlock();
        return false;
    }

    // 取出数据的线程
    void outMsgRescQueue()
    {
        int command = 0;

        for (int i = 0; i < 100000; ++i)
        {
            bool result = outMsgLULPro(command);
            if (result == true)
            {
                cout << "outMsgRescQueue()执行,取出一个元素" << command << endl;
            }
            else
            {
                cout << "outMsgRescQueue()执行,但目前消息队列为空" << i << endl;
            }
        }
        cout << "end" << endl;
    }

private:
    std::list msgRecvQueue; // 命令接收list
    st

你可能感兴趣的:(C++)