熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A
看到“死鎖”二字,你是不是慌得不知所措。死鎖,顧名思義就是這個鎖死掉了,再也動不了了。那死鎖是怎么產(chǎn)生的呢?當你對某個資源上鎖后,卻遲遲沒有釋放或者根本就無法釋放,導致別的線程無法獲得該資源的訪問權限,進而程序無法運行下去,有點像是阻塞的現(xiàn)象。但是阻塞是一種正常現(xiàn)象,而死鎖可以說是一種bug,必須要處理。
那么我現(xiàn)在就舉個死鎖的例子,來分析分析。
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mt1;
mutex mt2;
void thread1()
{
cout << "thread1 begin" << endl;
lock_guard<mutex> guard1(mt1);
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> guard2(mt2);
cout << "hello thread1" << endl;
}
void thread2()
{
cout << "thread2 begin" << endl;
lock_guard<mutex> guard1(mt2);
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> guard2(mt1);
cout << "hello thread2" << endl;
}
int main()
{
thread t1(thread1);
thread t2(thread2);
t1.join();
t2.join();
cout << "thread end" << endl;
return 0;
}
因為程序運行的是非??斓?,所以為了產(chǎn)生死鎖現(xiàn)象,我們各自休眠了1秒。
運行以上程序可以發(fā)現(xiàn),程序在輸出完“thread1 beginthread2 begin”后,就卡在那里,程序運行可能發(fā)生了以下這種情況:
thread1 thread2
mt1.lock() mt2.lock()
//死鎖 //死鎖
mt2.lock() mt1.lock()
thread1中的mt2在等待著thread2的mt2釋放鎖,而thead2中mt1卻也在等待著thread1的mt1釋放鎖,互相都在等待著對方釋放鎖,進而產(chǎn)生了死鎖。必須強調(diào)的是,這是一種bug,必須避免。那么如何避免這種情況呢?
1、每次都先鎖同一個鎖
比如像上面thread1和thread2線程,我們每次都先鎖mt1,再鎖mt2,就不會發(fā)生死鎖現(xiàn)象。
2、給鎖定義一個層次的屬性,每次按層次由高到低的順序上鎖,這個原理也是每次都先鎖同一個鎖。
C++標準庫中提供了std::lock()函數(shù),能夠保證將多個互斥鎖同時上鎖。
std::lock(mt1, mt2);
那么既然在最前面就已經(jīng)上鎖了,后面就不需要上鎖了,而C++標準庫并沒有提供std::unlock()的用法,所以還是需要用到lock_guard,但是需要修改一點。加個std::adopt_lock就可以了。
lock_guard<mutex> guard1(mt1, adopt_lock);
lock_guard<mutex> guard2(mt2, adopt_lock);
這個表示構造函數(shù)的時候不要給我上鎖,到析構的時候你要記得給我解鎖。
這個就是死鎖的一些解決方法,同時大家一定要記得盡量不要一段定義域內(nèi)多次使用互斥鎖,如果不可避免的要使用,一定要記得給鎖定義順序,或者使用要使用std::lock()上鎖。
相關閱讀:
熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A