zoukankan      html  css  js  c++  java
  • C++多线程死锁

           死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况。在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成。

    死锁出现的场景:当代码中有2个锁,锁A和锁B,也有2个线程,线程1和线程2,线程1执行时,先抢到锁A,然后要去抢占B,同时线程2先抢到了锁B,然后要去抢占锁A,此时就出现死锁情况,互相等待资源,又不释放自身的资源。

    如下代码:

    #include <iostream>
    #include<thread>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<windows.h>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class myClass
    {
    public:
        void AddOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                cout << "addOrder执行,插入一个元素" << i << endl;
                m_mutex1.lock();
                m_mutex2.lock();
                m_orderList.push_back(i);
                m_mutex1.unlock();
                m_mutex2.unlock();
            }
        }
    
        void RemoveOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                m_mutex2.lock();
                m_mutex1.lock();
                if (!m_orderList.empty())
                {
                    int i = m_orderList.front();
                    m_orderList.pop_front();
                    cout << "RemoveOrder执行,删除一个元素11111111111111111111" << i << endl;
                }
                m_mutex1.unlock();
                m_mutex2.unlock();
            }
        }
    
    private:
        std::list<int> m_orderList;
        std::mutex m_mutex1;
        std::mutex m_mutex2;
    };
    
    int main()
    {
        myClass my;
    
        std::thread obj1(&myClass::AddOrder, &my);
        std::thread obj2(&myClass::RemoveOrder, &my);
        obj1.join();
        obj2.join();
        
        system("pause");
    }
    View Code

    解决方法:std::lock()

      std::lock()的作用是:当有2给锁时,要么同时锁上,要么同时不锁。就是当线程1执行时,先抢到锁A,然后发现锁B被别人占用时,此时抢不到锁B,然后它就会把A锁也释放掉。

    代码如下:

    #include <iostream>
    #include<thread>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<windows.h>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class myClass
    {
    public:
        void AddOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                cout << "addOrder执行,插入一个元素" << i << endl;
                std::lock(m_mutex1, m_mutex2);
                m_orderList.push_back(i);
                m_mutex1.unlock();
                m_mutex2.unlock();
            }
        }
    
        void RemoveOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                std::lock(m_mutex2, m_mutex1);
                if (!m_orderList.empty())
                {
                    int i = m_orderList.front();
                    m_orderList.pop_front();
                    cout << "RemoveOrder执行,删除一个元素11111111111111111111" << i << endl;
                }
                m_mutex1.unlock();
                m_mutex2.unlock();
            }
        }
    
    private:
        std::list<int> m_orderList;
        std::mutex m_mutex1;
        std::mutex m_mutex2;
    };
    
    int main()
    {
        myClass my;
    
        std::thread obj1(&myClass::AddOrder, &my);
        std::thread obj2(&myClass::RemoveOrder, &my);
        obj1.join();
        obj2.join();
        
        system("pause");
    }
    View Code

    以下是对上面代码优化,用到了lock_guard,防止上锁后忘记解锁。std::adopt_lock作用取消上锁功能

    #include <iostream>
    #include<thread>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<windows.h>
    #include<list>
    #include<mutex>
    
    using namespace std;
    
    class myClass
    {
    public:
        void AddOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                cout << "addOrder执行,插入一个元素" << i << endl;
                std::lock(m_mutex1, m_mutex2);
                std::lock_guard<std::mutex> guard1(m_mutex1, std::adopt_lock);       //std::adopt_lock作用:取消对锁1上锁,因为上一句已经对锁1进行了上锁
                std::lock_guard<std::mutex> guard2(m_mutex2, std::adopt_lock);
                m_orderList.push_back(i);
            }
        }
    
        void RemoveOrder()
        {
            for (int i = 0; i < 10000; i++)
            {
                std::lock(m_mutex2, m_mutex1);
                std::lock_guard<std::mutex> guard1(m_mutex1, std::adopt_lock);
                std::lock_guard<std::mutex> guard2(m_mutex2, std::adopt_lock);
                if (!m_orderList.empty())
                {
                    int i = m_orderList.front();
                    m_orderList.pop_front();
                    cout << "RemoveOrder执行,删除一个元素" << i << endl;
                }
            }
        }
    
    private:
        std::list<int> m_orderList;
        std::mutex m_mutex1;
        std::mutex m_mutex2;
    };
    
    int main()
    {
        myClass my;
    
        std::thread obj1(&myClass::AddOrder, &my);
        std::thread obj2(&myClass::RemoveOrder, &my);
        obj1.join();
        obj2.join();
        
        system("pause");
    }
    View Code
    111
  • 相关阅读:
    python_函数_文件
    Day_2_Python_str_list_dict的使用
    Day_1_Python_循环和格式化
    influxdb2.0版本部署+自启
    格式化Java内存工具JOL输出
    卷心菜的屯币日记
    influxDB时序数据库2.0FLUX查询语法使用记录
    两种转换2021-01-01T00:00:00Z为2021-01-01 00:00:00时间格式的方式(UTC时间转为yyyy-MM-dd HH:mm:ss)
    ThreadLocal的用处
    CentOS7使用ISO镜像文件作为离线Yum源
  • 原文地址:https://www.cnblogs.com/zwj-199306231519/p/13544533.html
Copyright © 2011-2022 走看看