若是熟悉C++多線程的童鞋可能有了解到實現的互斥鎖的機制還有這個寫法ios
lock_guard<mutex> guard(mt);
那麼這句話是什麼意思呢?爲何又要搞個這樣的寫法呢?多線程
這個也是構造互斥鎖的寫法,就是會在lock_guard構造函數里加鎖,在析構函數裏解鎖,之因此搞了這個寫法,C++委員會的解釋是防止使用mutex加鎖解鎖的時候,忘記解鎖unlock了。函數
#include <iostream> #include <thread> #include <string> #include <mutex>
using namespace std; mutex mt; void thread_task() { for (int i = 0; i < 10; i++) { lock_guard<mutex> guard(mt); cout << "print thread: " << i << endl; } } int main() { thread t(thread_task); for (int i = 0; i > -10; i--) { lock_guard<mutex> guard(mt); cout << "print main: " << i << endl; } t.join(); return 0; }
這裏說析構函數裏解鎖,那麼到底何時調用析構函數呢?構造函數加鎖咱們好理解,寫下這個語句的時候調用lock_guard<mutex> guard(mt),那麼調用析構函數應該是大括號{}結束的時候,也就是說定義lock_guard的時候調用構造函數加鎖,大括號解鎖的時候調用析構函數解鎖。學習
雖然lock_guard挺好用的,可是有個很大的缺陷,在定義lock_guard的地方會調用構造函數加鎖,在離開定義域的話lock_guard就會被銷燬,調用析構函數解鎖。這就產生了一個問題,若是這個定義域範圍很大的話,那麼鎖的粒度就很大,很大程序上會影響效率。spa
因此爲了解決lock_guard鎖的粒度過大的緣由,unique_lock就出現了。線程
unique_lock<mutex> unique(mt);調試
這個會在構造函數加鎖,而後能夠利用unique.unlock()來解鎖,因此當你以爲鎖的粒度太多的時候,能夠利用這個來解鎖,而析構的時候會判斷當前鎖的狀態來決定是否解鎖,若是當前狀態已是解鎖狀態了,那麼就不會再次解鎖,而若是當前狀態是加鎖狀態,就會自動調用unique.unlock()來解鎖。而lock_guard在析構的時候必定會解鎖,也沒有中途解鎖的功能。code
固然,方便確定是有代價的,unique_lock內部會維護一個鎖的狀態,因此在效率上確定會比lock_guard慢。blog
因此,以上兩種加鎖解鎖的方法,加上前面文章介紹的mutex方法,具體該使用哪個,要依照具體的業務需求來決定,固然mt.lock()和mt.unlock()無論是哪一種狀況,是確定均可以使用的。string
對我而言,總感受這個lock_guard有點雞肋而已,徹底能夠用mutex來替代,忘記解鎖的話通常均可以經過調試發現,並且通常狀況下都不會忘記。僅僅只是由於怕忘記解鎖這個緣由的話,真的感受有點畫蛇添足,徒增學習成本罷了。
固然也許C++委員會有他們本身的考慮,對於咱們而言,也只能記住就是了。
更多精彩內容,請關注同名公衆:一點筆記alittle