可重入鎖與不可重入鎖以及常見的死鎖現象

2021-09-26 14:19:28 字數 1638 閱讀 6266

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 ...