C++ 11中l(wèi)ock_guard和unique_lock的區(qū)別
在C++11中,std::lock_guard 和 std::unique_lock 都是用于管理互斥鎖(std::mutex 或其他互斥鎖類型)的RAII(資源獲取即初始化)類,但它們在功能和使用場景上有一些重要的區(qū)別。以下是它們的主要區(qū)別:
一、功能設(shè)計
1.1 std::lock_guard
功能單一:std::lock_guard 的唯一目的是在構(gòu)造時鎖定互斥鎖,并在析構(gòu)時釋放互斥鎖。它不支持手動解鎖。
使用場景:適用于需要在某個作用域內(nèi)簡單地鎖定和解鎖互斥鎖的場景,且不需要中途解鎖。
代碼示例:
#include<thread>
#include<mutex>
std::mutex mt;
void function()
{
// 構(gòu)造lock對象時,鎖定
std::lock_guard<std::mutex> lock(mt);
// 在這個作用域內(nèi),互斥鎖保持鎖定狀態(tài)
...
// lock 對象析構(gòu)時,互斥鎖自動解鎖。
}
1.2 std::unique_lock
功能豐富:std::unique_lock 提供了更靈活的鎖管理功能。它支持手動鎖定和解鎖,還可以在構(gòu)造時不立即鎖定互斥鎖。
使用場景:適用于需要更靈活地控制鎖的場景,例如在條件變量等待時需要解鎖互斥鎖,或者在某些條件下才鎖定互斥鎖。
代碼示例:
#include<thread>
#include<mutex>
std::mutex mt;
void function()
{
// 構(gòu)造lock對象時,鎖定
std::unique_lock<std::mutex> lock(mt);
// 手動解鎖
lock.unlock();
// 在這個作用域內(nèi),互斥鎖是解鎖狀態(tài)
...
// 從新鎖定
lock.lock();
// lock 對象析構(gòu)時,互斥鎖自動解鎖。
}
二、構(gòu)造方式
2.1 std::lock_guard
- 構(gòu)造時必須傳遞一個互斥鎖對象,并且會立即鎖定該互斥鎖。
構(gòu)造函數(shù):
explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
_MyMutex.lock();
}
lock_guard(_Mutex& _Mtx, adopt_lock_t) noexcept // strengthened
: _MyMutex(_Mtx) {} // construct but don't lock
- 默認情況下,會立即鎖定互斥鎖。
- 如果傳遞了
std::adopt_lock,表示互斥鎖已經(jīng)被當(dāng)前線程鎖定,std::lock_guard只負責(zé)管理鎖的釋放。
2.2 std::unique_lock
構(gòu)造時可以選擇不立即鎖定互斥鎖,或者傳遞一個已經(jīng)鎖定的互斥鎖。
構(gòu)造函數(shù):
_NODISCARD_CTOR_LOCK explicit unique_lock(_Mutex& _Mtx)
: _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // construct and lock
_Pmtx->lock();
_Owns = true;
}
_NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, adopt_lock_t) noexcept // strengthened
: _Pmtx(_STD addressof(_Mtx)), _Owns(true) {} // construct and assume already locked
unique_lock(_Mutex& _Mtx, defer_lock_t) noexcept
: _Pmtx(_STD addressof(_Mtx)), _Owns(false) {} // construct but don't lock
- 默認情況下,不會立即鎖定互斥鎖(需要手動調(diào)用
lock())。 - 如果傳遞了
std::defer_lock,表示延遲鎖定,需要手動調(diào)用lock()。 - 如果傳遞了
std::adopt_lock,表示互斥鎖已經(jīng)被當(dāng)前線程鎖定,std::unique_lock只負責(zé)管理鎖的釋放。
三、解鎖能力
3.1 std::lock_guard
- 不支持手動解鎖。互斥鎖只能在
std::lock_guard對象析構(gòu)時自動解鎖。
3.2 std::unique_lock
- 支持手動解鎖??梢酝ㄟ^調(diào)用
unlock()方法手動釋放互斥鎖,也可以在析構(gòu)時自動解鎖。 - 代碼示例:
std::unique_lock<std::mutex> lock(mtx, std::defer_lock); // 延遲鎖定 lock.lock(); // 手動鎖定 lock.unlock(); // 手動解鎖
四、與條件變量的配合
4.1 std::lock_guard
- 由于不支持手動解鎖,因此不能與條件變量配合使用。條件變量需要在等待時釋放互斥鎖,并在被喚醒后重新鎖定。
4.2 std::unique_lock
- 與條件變量配合使用時非常方便。
std::unique_lock可以在等待條件變量時手動解鎖互斥鎖,并在條件變量被喚醒后重新鎖定。
#include<thread>
#include<mutex>
#include<condition_variable>
std::mutex mt;
std::condition_variable cv;
bool bReady = false;
// 生產(chǎn)者
void producer()
{
// 構(gòu)造lock對象時,鎖定
std::unique_lock<std::mutex> lock(mt);
// Do Something
...
// 解鎖
lock.unlock();
// 通知消費者
cv.notify_one();
}
void customer()
{
// 構(gòu)造lock對象時,鎖定
std::unique_lock<std::mutex> lock(mt);
// 條件變量等待時自動解鎖和重新鎖定
cv.wait(lock,[]{return bReady;});
// 繼續(xù)處理
}
五、性能和開銷
- std::lock_guard
- 由于功能簡單,通常比 std::unique_lock 更輕量級,生成的代碼可能更高效。
- std::unique_lock
- 功能更復(fù)雜,可能帶來一些額外的開銷,但這種開銷在大多數(shù)情況下是可以忽略的。
總結(jié)
- 如果你只需要在某個作用域內(nèi)簡單地鎖定和解鎖互斥鎖,且不需要中途解鎖,那么
std::lock_guard是更好的選擇。 - 如果你需要更靈活地控制鎖的鎖定和解鎖,或者需要與條件變量配合使用,那么
std::unique_lock是更合適的選擇。
到此這篇關(guān)于C++ 11中l(wèi)ock_guard和unique_lock的區(qū)別的文章就介紹到這了,更多相關(guān)C++ 11 lock_guard和unique_lock 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)查找二叉樹中和為某一值的所有路徑的示例
這篇文章主要介紹了C++實現(xiàn)查找二叉樹中和為某一值的所有路徑的示例,文中的方法是根據(jù)數(shù)組生成二叉排序樹并進行遍歷,需要的朋友可以參考下2016-02-02
C++實現(xiàn)LeetCode(12.整數(shù)轉(zhuǎn)化成羅馬數(shù)字)
這篇文章主要介紹了C++實現(xiàn)LeetCode(12.整數(shù)轉(zhuǎn)化成羅馬數(shù)字),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
C語言判斷數(shù)是否為素數(shù)與素數(shù)輸出
大家好,本篇文章主要講的是C語言判斷數(shù)是否為素數(shù)與素數(shù)輸出,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12

