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>
- 擁有方法std::unique_lock<std::mutex>::owns_lock(),判斷當前是否鎖定該鎖。
- 擁有方法std::unique_lock<std::mutex>::try_lock(),嘗試加鎖,如果返回true則加鎖成功,否則加鎖失敗,不阻塞。
- 擁有方法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>
- try_lock_for()函數:等待一段時間。如果拿到鎖或者等待超時,就往下執行。
- 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{
... //沒有拿到鎖
}
以上內容,詳情查看文檔