C++中unique_lock和lock_guard區(qū)別小結(jié)
在 C++ 中,std::unique_lock
和 std::lock_guard
都屬于標(biāo)準(zhǔn)庫 <mutex>
中的互斥鎖管理工具,用于簡化互斥鎖的使用并確保線程安全。但它們存在一些顯著區(qū)別,下面為你詳細(xì)介紹:
1.自動鎖定與解鎖機(jī)制
1) std::lock_guard
:一個輕量級的互斥鎖包裝器,采用了 RAII(資源獲取即初始化)技術(shù)。當(dāng) std::lock_guard
對象被創(chuàng)建時,它會自動鎖定所關(guān)聯(lián)的互斥鎖;當(dāng)對象離開其作用域時,會自動解鎖該互斥鎖。它的設(shè)計遵循最小化原則,僅提供最基本的鎖管理功能,沒有額外的開銷。其核心實(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ù)或移動賦值運(yùn)算符將互斥鎖的所有權(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
對象,因?yàn)樵诘却陂g需要釋放和重新獲取鎖。
#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)文章
C++連接數(shù)據(jù)庫SqlServer、MySql、Oracle、Access、SQLite、PostgreSQL、Mong
C++是一種通用的編程語言,可以使用不同的庫和驅(qū)動程序來連接各種數(shù)據(jù)庫,以下是一些示例代碼,演示如何使用?C++?連接?SQL?Server、MySQL、Oracle、ACCESS、SQLite?、?PostgreSQL、MongoDB、Redis數(shù)據(jù)庫2024-08-08Qt?10進(jìn)制和16進(jìn)制轉(zhuǎn)換的使用示例
在編程過程中,處理16進(jìn)制字符串與10進(jìn)制數(shù)字之間的轉(zhuǎn)換是很常見的需求,本文主要介紹了Qt?10進(jìn)制和16進(jìn)制轉(zhuǎn)換的使用示例,具有一定的參考價值,感興趣的可以了解一下2023-09-09C++實(shí)現(xiàn)LeetCode(90.子集合之二)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(90.子集合之二),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++實(shí)現(xiàn)std::set的示例項(xiàng)目
std::set是C++標(biāo)準(zhǔn)庫中的關(guān)聯(lián)容器,提供有序唯一元素集合,本文就來介紹一下std::set的具體使用,具有一定的參考價值,感興趣的可以了解一下2025-02-02Cocos2d-x 3.x入門教程(一):基礎(chǔ)概念
這篇文章主要介紹了Cocos2d-x 3.x入門教程(一):基礎(chǔ)概念,本文講解了Director、Scene、Layer、Sprite等內(nèi)容,需要的朋友可以參考下2014-11-11