C++中unique_lock和lock_guard區(qū)別小結(jié)
在 C++ 中,std::unique_lock 和 std::lock_guard 都屬于標(biāo)準(zhǔn)庫 <mutex> 中的互斥鎖管理工具,用于簡化互斥鎖的使用并確保線程安全。但它們存在一些顯著區(qū)別,下面為你詳細(xì)介紹:
1.自動鎖定與解鎖機制
1) std::lock_guard:一個輕量級的互斥鎖包裝器,采用了 RAII(資源獲取即初始化)技術(shù)。當(dāng) std::lock_guard 對象被創(chuàng)建時,它會自動鎖定所關(guān)聯(lián)的互斥鎖;當(dāng)對象離開其作用域時,會自動解鎖該互斥鎖。它的設(shè)計遵循最小化原則,僅提供最基本的鎖管理功能,沒有額外的開銷。其核心實現(xiàn)原理可以簡化為:
template<classMutex>
classlock_guard {
public:
explicitlock_guard(Mutex& m) : mutex(m) {
mutex.lock();
}
~lock_guard() {
mutex.unlock();
}
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
Mutex& mutex;
};示例代碼如下:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void printMessage() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "This message is protected by lock_guard." << std::endl;
// 當(dāng) lock_guard 對象離開作用域時,互斥鎖會自動解鎖
}
int main() {
std::thread t(printMessage);
t.join();
return 0;
}2) std::unique_lock: 同樣基于 RAII 技術(shù),在對象銷毀時會自動解鎖互斥鎖。不過,它的鎖定和解鎖操作更加靈活,可以在對象創(chuàng)建時選擇不立即鎖定互斥鎖,也可以在對象生命周期內(nèi)手動鎖定和解鎖。unique_lock 是 C++11 標(biāo)準(zhǔn)中引入的更高級的鎖管理器,設(shè)計目標(biāo)是提供更靈活的鎖管理能力。其核心接口包括:
class unique_lock {
public:
// 構(gòu)造時可選立即加鎖、延遲加鎖或嘗試加鎖
unique_lock(mutex_type& m, std::defer_lock_t) noexcept;
unique_lock(mutex_type& m, std::try_to_lock_t);
unique_lock(mutex_type& m, std::adopt_lock_t);
// 轉(zhuǎn)移構(gòu)造函數(shù)
unique_lock(unique_lock&& other) noexcept;
// 手動控制接口
voidlock();
booltry_lock();
voidunlock();
// 狀態(tài)查詢
explicitoperatorbool()constnoexcept;
boolowns_lock()constnoexcept;
};示例代碼如下:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void printMessage() {
std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
// 手動鎖定互斥鎖
lock.lock();
std::cout << "This message is protected by unique_lock." << std::endl;
// 手動解鎖互斥鎖
lock.unlock();
}
int main() {
std::thread t(printMessage);
t.join();
return 0;
}std::unique_lock 允許在對象生命周期內(nèi)多次手動調(diào)用 lock()、unlock() 和 try_lock() 方法。這在需要在臨界區(qū)內(nèi)進(jìn)行部分操作后暫時釋放鎖,執(zhí)行一些非關(guān)鍵操作,然后再次鎖定的場景中很有用。如:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void work() {
std::unique_lock<std::mutex> lock(mtx);
std::cout << "Entered critical section." << std::endl;
// 執(zhí)行部分臨界區(qū)操作
lock.unlock();
std::cout << "Temporarily released the lock." << std::endl;
// 執(zhí)行一些非關(guān)鍵操作
lock.lock();
std::cout << "Re - entered critical section." << std::endl;
// 繼續(xù)執(zhí)行臨界區(qū)操作
}
int main() {
std::thread t(work);
t.join();
return 0;
}2.靈活性
1)std::lock_guard: 功能相對單一,缺乏靈活性。一旦創(chuàng)建,就會立即鎖定互斥鎖,并且在其生命周期內(nèi)無法手動解鎖,只能在對象離開作用域時自動解鎖。
2)std::unique_lock:具有更高的靈活性。它支持三種鎖定策略:
std::defer_lock_t // 延遲鎖定 std::try_to_lock_t // 嘗試鎖定 std::adopt_lock_t // 接管已鎖定狀態(tài)
- 延遲鎖定(
std::defer_lock):創(chuàng)建std::unique_lock對象時,可以選擇不立即鎖定互斥鎖。這在需要先進(jìn)行一些準(zhǔn)備工作,之后再鎖定互斥鎖的場景中非常有用。如:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void work() {
std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
// 進(jìn)行一些無需加鎖的準(zhǔn)備工作
std::cout << "Doing some preparation work..." << std::endl;
lock.lock();
std::cout << "Critical section entered." << std::endl;
// 臨界區(qū)代碼
lock.unlock();
std::cout << "Critical section exited." << std::endl;
}
int main() {
std::thread t(work);
t.join();
return 0;
}- 嘗試鎖定(
std::try_to_lock):使用std::try_to_lock可以嘗試鎖定互斥鎖,如果互斥鎖當(dāng)前已被其他線程鎖定,std::unique_lock對象不會阻塞,而是立即返回,可通過owns_lock()方法判斷是否成功鎖定。如:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void work() {
std::unique_lock<std::mutex> lock(mtx, std::try_to_lock);
if (lock.owns_lock()) {
std::cout << "Successfully locked the mutex." << std::endl;
// 臨界區(qū)代碼
} else {
std::cout << "Failed to lock the mutex, doing other work." << std::endl;
// 執(zhí)行其他不需要鎖定互斥鎖的工作
}
}
int main() {
std::thread t(work);
t.join();
return 0;
}3.所有權(quán)轉(zhuǎn)移
std::lock_guard:
- 不支持所有權(quán)轉(zhuǎn)移,即不能將一個
std::lock_guard對象的互斥鎖所有權(quán)轉(zhuǎn)移給另一個對象。
std::unique_lock:
- 支持所有權(quán)轉(zhuǎn)移,可以通過移動構(gòu)造函數(shù)或移動賦值運算符將互斥鎖的所有權(quán)從一個
std::unique_lock對象轉(zhuǎn)移到另一個對象。這在函數(shù)返回std::unique_lock對象或需要在不同作用域之間傳遞鎖的所有權(quán)時非常有用。
示例代碼如下:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
std::unique_lock<std::mutex> getLock() {
std::unique_lock<std::mutex> lock(mtx);
return std::move(lock);
}
void printMessage() {
std::unique_lock<std::mutex> lock = getLock();
std::cout << "This message is protected by transferred unique_lock." << std::endl;
}
int main() {
std::thread t(printMessage);
t.join();
return 0;
}4.可與條件變量配合使用
std::unique_lock 能夠與 std::condition_variable 一起使用,std::condition_variable 的 wait()、wait_for() 和 wait_until() 等方法要求傳入 std::unique_lock 對象,因為在等待期間需要釋放和重新獲取鎖。
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; });
std::cout << "Worker thread is working." << std::endl;
}
int main() {
std::thread t(worker);
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
t.join();
return 0;
}5.性能開銷
std::lock_guard:
- 由于其功能簡單,沒有額外的狀態(tài)管理,因此性能開銷相對較小,適合用于簡單的鎖定場景。
std::unique_lock:
- 為了支持更多的靈活性,
std::unique_lock需要維護(hù)更多的狀態(tài)信息,因此性能開銷相對較大。在對性能要求極高且鎖定邏輯簡單的場景下,使用std::lock_guard更為合適。
綜上所述,std::lock_guard 適用于簡單的鎖定場景,追求簡潔性和較低的性能開銷;而 std::unique_lock 則適用于需要更復(fù)雜鎖定邏輯、支持所有權(quán)轉(zhuǎn)移的場景,但會帶來一定的性能開銷。
到此這篇關(guān)于C++中unique_lock和lock_guard區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)C++ unique_lock和lock_guard區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt框架中QPushButton 和 QToolButton的使用小結(jié)
本文對比了Qt框架中的兩種按鈕控件QPushButton和QToolButton,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-11-11
C++實現(xiàn)LeetCode(642.設(shè)計搜索自動補全系統(tǒng))
這篇文章主要介紹了C++實現(xiàn)LeetCode(642.設(shè)計搜索自動補全系統(tǒng)),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
一文學(xué)會數(shù)據(jù)結(jié)構(gòu)-堆
本文主要介紹了數(shù)據(jù)結(jié)構(gòu)-堆,文中通過圖片和大量的代碼講解的非常詳細(xì),需要學(xué)習(xí)的朋友可以參考下這篇文章,希望可以幫助到你2021-08-08
QT中在QLabel顯示圖片并且利用鼠標(biāo)點擊畫線問題
這篇文章主要介紹了QT中在QLabel顯示圖片并且利用鼠標(biāo)點擊畫線問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11

