第六節 unique_lock(類模闆)詳解
1.unique_lock取代lock_guard
unique_lock比lock_guard靈活很多(多出來很多用法),效率差一點。
unique_lock myUniLock(myMutex);
2.unique_lock的第二個參數
2.1 std::adopt_lock:
- 表示這個互斥量已經被lock(),即不需要在構造函數中lock這個互斥量了。
- 前提:必須提前lock
- lock_guard中也可以用這個參數
2.2 std::try_to_lock:
- 嘗試用mutx的lock()去鎖定這個mutex,但如果沒有鎖定成功,會立即傳回,不會阻塞在那裡;
- 使用try_to_lock的原因是防止其他的線程鎖定mutex太長時間,導緻本線程一直阻塞在lock這個地方
- 前提:不能提前lock();
- owns_locks()方法判斷是否拿到鎖,如拿到傳回true
2.3 std::defer_lock:
- 如果沒有第二個參數就對mutex進行加鎖,加上defer_lock是始化了一個沒有加鎖的mutex
- 不給它加鎖的目的是以後可以調用unique_lock的一些方法
- 前提:不能提前lock
3.unique_lock的成員函數(前三個與std::defer_lock聯合使用)
3.1 lock():加鎖。
unique_lock<mutex> myUniLock(myMutex, defer_lock);
myUniLock.lock();
不用自己unlock();
3.2 unlock():解鎖。
unique_lock<mutex> myUniLock(myMutex, defer_lock);
myUniLock.lock();
//處理一些共享代碼
myUniLock.unlock();
//處理一些非共享代碼
myUniLock.lock();
//處理一些共享代碼
因為一些非共享代碼要處理,可以暫時先unlock(),用其他線程把它們處理了,處理完後再lock()。
3.3 try_lock():嘗試給互斥量加鎖
如果拿不到鎖,傳回false,否則傳回true。
3.4 release():
-
unique_lock
myUniLock(myMutex);相當于把myMutex和myUniLock綁定在了一起,release()就是解除綁定,傳回它所管理的mutex對象的指針,并釋放所有權
-
mutex* ptx =
myUniLock.release();所有權由ptx接管,如果原來mutex對象處理加鎖狀态,就需要ptx在以後進行解鎖了。
lock的代碼段越少,執行越快,整個程式的運作效率越高。
a.鎖住的代碼少,叫做粒度細,執行效率高;
b.鎖住的代碼多,叫做粒度粗,執行效率低;
4.unique_lock所有權的傳遞
unique_lock myUniLock(myMutex);把myMutex和myUniLock綁定在了一起,也就是myUniLock擁有myMutex的所有權
1. 使用move轉移
- myUniLock擁有myMutex的所有權,myUniLock可以把自己對myMutex的所有權轉移,但是不能複制。
-
unique_lock myUniLock2(std::move(myUniLock));
現在myUniLock2擁有myMutex的所有權。
2. 在函數中return一個臨時變量,即可以實作轉移
unique_lock<mutex> aFunction()
{
unique_lock<mutex> myUniLock(myMutex);
//移動構造函數那裡講從函數傳回一個局部的unique_lock對象是可以的
//傳回這種局部對象會導緻系統生成臨時的unique_lock對象,并調用unique_lock的移動構造函數
return myUniLock;
}