C++ mutex lock_guard unique_lock使用說明

1. std::mutex

類似函數std::recursive_mutex 允許同一個線程多次獲取同一個互斥量

頭文件#include <mutex>

mutex::lock(),給共享內存加鎖

...

...  //待保護代碼或者共享內存等等

...

mutex::unlock(),給共享內存解鎖

比如:

std::mutex m;

m.lock();

...

m.unlock();

 

2. std::lock_guard<std::mutex> (模板類)

頭文件#include <mutex>

比如:

1)

std::mutex m;

{

std::lock_gurad<std::mutex> lguard(m); //類中默認加鎖作用域,作用域執行完畢類析構中自動解鎖

... //作用域在大括號中,作用域結束,lguard自動unlock。

}

2)

std::mutex m;

{

m.lock();

std::lock_guard<std::mutex> lguard(m, std::adopt_lock); //使用adopt_lock選項默認爲未加鎖,但是執行完作用域類析構函數中自動解鎖。

...  //作用域在大括號內,作用域結束,lguard自動unlock。

}

3)

std::mutex m;

{

std::lock_guard<std::mutex> lguard(m); //默認已經加鎖

std::mutex *pmtx = lguard.release(); //解除lguard和m之間的關聯關係,此時m已經加鎖,並未解鎖,所以後面需要解鎖

...  //作用域在大括號內,作用域結束,lguard自動unlock。

pmtx->unlock();

}

 

3. std::unique_lock<std::mutex>

頭文件#include <mutex>

  1. 擁有方法std::unique_lock<std::mutex>::owns_lock(),判斷當前是否鎖定該鎖。
  2. 擁有方法std::unique_lock<std::mutex>::try_lock(),嘗試加鎖,如果返回true則加鎖成功,否則加鎖失敗,不阻塞。
  3. 擁有方法std::unique_lock<std::mutex>::release(),返回它管理的mutex對象指針,並釋放所有權;也就是說,這個unique_lock和mutex不在有關係。

比如:

1)

std::mutex m;

{

std::unique_gurad<std::mutex> uguard(m); //類中默認加鎖作用域,作用域執行完畢類析構中自動解鎖

... //作用域在大括號中,作用域結束,uguard自動unlock。

}

2)

std::mutex m;

{

m.lock();

std::unique_guard<std::mutex> uguard(m, std::adopt_lock); //使用adopt_lock選項默認爲未加鎖,但是執行完作用域類析構函數中自動解鎖。

...  //作用域在大括號內,作用域結束,uguard自動unlock。

}

3)

std::mutex m;

{

std::unique_guard<std::mutex> uguard(m, std::try_to_lock); //解決一個線程加鎖後佔用事件較長,另一個線程等待較長時間的問題

...  //作用域在大括號內,作用域結束,uguard自動unlock。

}

4)

std::mutex m;

{

std::unique_guard<std::mutex> uguard(m, std::defer_lock); //1. 解決線程臨時需要釋放鎖,之後再次加鎖的情況。2. 如果後面不使用lock和unlock功能和示例3一樣。

uguard.lock(); //加鎖

...  //作用域在大括號內,作用域結束,uguard自動unlock。

 

另外也可以手動lock和unlock。

uguard.unlock();

...

...

uguard.lock();

...

...

uguard.unlock();

}

5)

std::mutex m;

{

std::unique_guard<std::mutex> uguard(m, std::defer_lock); //1. 解決線程臨時需要釋放鎖,之後再次加鎖的情況。2. 如果後面不使用lock和unlock功能和示例3一樣。

uguard.lock(); //加鎖

...  //作用域在大括號內,作用域結束,uguard自動unlock。

 

if( uguard.owns_lock() == true){

... //加鎖成功,執行共享內存代碼

}

else{

... //加鎖沒有成功

}

}

6)

std::mutex m;

{

std::unique_guard<std::mutex> uguard(m, std::defer_lock); //1. 解決線程臨時需要釋放鎖,之後再次加鎖的情況。2. 如果後面不使用lock和unlock功能和示例3一樣。

 

...  //作用域在大括號內,作用域結束,uguard自動unlock。

 

if(uguard.try_lock() == true){

... //加鎖成功,執行共享內存代碼

}

else{

... //加鎖沒有成功

}

}

7)

std::mutex m;

{

std::unique_guard<std::mutex> uguard(m); //默認已經加鎖

std::mutex *pmtx = uguard.release(); //解除uguard和m之間的關聯關係,此時m已經加鎖,並未解鎖,所以後面需要解鎖

...  //作用域在大括號內,作用域結束,uguard自動unlock。

pmtx->unlock();

}

 

4. std::lock()函數

功能:一次加多把鎖,避免死鎖

頭文件:#include <mutex>

比如:

1)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同時上鎖

... //訪問共享變量

m1.unlock();

m2.unlock();

2)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同時上鎖

std::lock_guard<std::mutex> lguard1(m1, std::adopt_lock); //用lock_guard自動unlock鎖

std::lock_guard<std::mutex> lguard2(m2, std::adopt_lock);

... //訪問共享變量

//不再需要unlock鎖m1和m2了

3)

std::mutex m1, m2;

std::lock(m1, m2) //m1,m2同時上鎖

std::unique_guard<std::mutex> uguard1(m1, std::adopt_lock); //用lock_guard自動unlock鎖

std::unique_guard<std::mutex> uguard2(m2, std::adopt_lock);

... //訪問共享變量

//不再需要unlock鎖m1和m2了

 

5. std::timed_mutex 帶超時功能的獨佔互斥量

類似函數std::recursive_timed_mutex 允許同一個線程多次獲取同一個互斥量

頭文件#include <mutex>

  1. try_lock_for()函數:等待一段時間。如果拿到鎖或者等待超時,就往下執行。
  2. try_lock_until()函數:參數是一個未來時間點,在未來一段時間內如果拿到鎖就走下來;如果時間到了沒有拿到鎖,程序也走下來。

比如:

1)

std::timed_mutex m;

std::chrono::millisecond timeout(100);

if(m.try_lock_for(timeout)){ //程序等待100毫秒嘗試拿鎖,如果拿到鎖執行if,否則else

... //拿到鎖,執行互斥內容

m.unlock();

}

else{

... //沒有拿到鎖

}

2)

std::timed_mutex m;

std::chrono::millisecond timeout(100);

if(m.try_lock_until(std::chrono::steady_clock::now() + timeout)){ //程序從當前時間開始經過100毫秒時間,如果拿到鎖,執行if,否則執行else

... //執行互斥內容

m.unlock();

}

else{

... //沒有拿到鎖

}

以上內容,詳情查看文檔

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章