死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况。在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成。
死锁出现的场景:当代码中有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"); }
解决方法: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"); }
以下是对上面代码优化,用到了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"); }