mutex可以分為遞迴鎖(recursive mutex)和非遞迴鎖(non-recursive mutex)。
windows下的mutex和critical section是可遞迴的。linux下的pthread_mutex_t鎖預設是非遞迴的。可以顯示的設定pthread_mutex_recursive屬性,將pthread_mutex_t設為遞迴鎖。
當兩個任務都在等待被對方持有的資源時,兩個任務都無法再繼續執行,這種情況就被稱為死鎖。
■ 死鎖情況1:
eg1: 濫用鎖導致
void foo()
void bar()
foo函式和bar函式都獲取了同乙個鎖,而bar函式又會呼叫foo函式。如果mutexlock鎖是個非遞迴鎖,則這個程式會立即死鎖。因此在為一段程式加鎖時要格外小心,否則很容易因為這種呼叫關係而造成死鎖。
原則上不應該出現這樣的**設計,不推崇在互斥鎖保護的區域使用使用者自定義的**。解決方案:
即使出現了這樣的情況,可以使用c++11推出的recursive_mutex(遞迴鎖)來解決或者系統提供的遞迴鎖能力。
新增乙個不加鎖版本 foo_without_lock()
■ 死鎖情況2:
thread a thread b
_mu.lock() _mu2.lock()
//死鎖 //死鎖
_mu2.lock() _mu.lock()
避免死鎖,有以下幾點建議:
建議盡量同時只對乙個互斥鎖上鎖。
不要在互斥鎖保護的區域使用使用者自定義的**,因為使用者的**可能操作了其他的互斥鎖。
如果想同時對多個互斥鎖上鎖,推薦使用std::scoped_lock(c++17)。
#include #include #include #include #include #include #include struct employee
std::string id;
std::vectorlunch_partners;
std::mutex m;
std::string output() const
}; void send_mail(employee &, employee &)
void assign_lunch_partner(employee &e1, employee &e2)
e1.lunch_partners.push_back(e2.id);
e2.lunch_partners.push_back(e1.id);
}send_mail(e1, e2);
send_mail(e2, e1);}
int main()
參考文章:
[c++11]多執行緒程式設計(四)——死鎖(dead lock)
執行緒同步之利器(1)——可遞迴鎖與非遞迴鎖
可重入鎖 不可重入鎖
可重入鎖指的是可重複可遞迴呼叫的鎖,在外層使用鎖之後,在內層仍然可以使用,並且不發生死鎖 前提是同乙個物件或者類 note reentrantlock和synchronized都是可重入鎖 1 public class testlock 78 public synchronized void tes...
可重入鎖和不可重入鎖
當乙個執行緒獲得當前例項的鎖lock,並且進入了方法a,該執行緒在方法a沒有釋放該鎖的時候,是否可以再次進入使用該鎖的方法b?不可重入鎖 在方法a釋放鎖之前,不可以再次進入方法b 可重入鎖 在方法a釋放該鎖之前可以再次進入方法b 如reentrantlock和synchronized 不可重入鎖的實...
可重入鎖和不可重入鎖
可重入鎖就是可以迴圈迭代使用的鎖,不會產生死鎖的現象,典型的就是synchronized和reentrantlock。不可重入鎖迴圈迭代使用則有產生死鎖的風險。可重入鎖 class reentranttest implements runnable public synchronized void ...