- 操作系統:ubuntu22.04
- IDE:Visual Studio Code
- 編程語言:C++11
算法描述
std::lock_guard 是 C++11 引入的一個 RAII(Resource Acquisition Is Initialization)風格的鎖管理類,用于自動管理互斥鎖(mutex)的加鎖和解鎖,確保在任何情況下(包括異常)都能正確釋放鎖。
核心作用
- 構造時加鎖
- 析構時自動解鎖
- 防止死鎖和資源泄漏
- 異常安全
? 它是最簡單、最安全的互斥鎖管理方式,適用于大多數臨界區保護場景。
頭文件
#include <mutex>
基本語法
std::lock_guard<std::mutex> lock(mutex_object);
- std::mutex:可以是任何標準互斥類型(如 std::mutex, std::recursive_mutex)
- lock:作用域內的鎖對象,名字可自定義
- mutex_object:已經定義的互斥量
使用示例
示例 1:保護共享變量
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
using namespace std;int counter = 0;
std::mutex mtx; // 全局互斥鎖void safe_increment(int n) {for (int i = 0; i < n; ++i) {// { 作用域開始std::lock_guard<std::mutex> lock(mtx); // 構造時加鎖counter++; // 安全訪問共享資源// } 作用域結束,lock 析構,自動解鎖}
}int main() {vector<thread> threads;// 創建 4 個線程for (int i = 0; i < 4; ++i) {threads.emplace_back(safe_increment, 10000);}// 等待所有線程完成for (auto& t : threads) {t.join();}cout << "Final counter value: " << counter << endl; // 應為 40000return 0;
}
構造函數
構造函數 | 說明 |
---|---|
explicit lock_guard(mutex_type& m); | 加鎖并管理 m |
lock_guard(mutex_type& m, std::defer_lock_t); | 不加鎖,僅管理(但 lock_guard 不支持 defer_lock)? |
lock_guard(mutex_type& m, std::adopt_lock_t); | 假設鎖已由當前線程持有,僅接管 |
?? 注意:std::lock_guard 不支持 std::defer_lock,它總是立即加鎖。如果需要延遲加鎖,請使用 std::unique_lock。
與 std::unique_lock 的對比
特性 | std::lock_guard | std::unique_lock |
---|---|---|
是否立即加鎖 | 是 | 可延遲(defer_lock) |
是否可手動解鎖 | 否 | 是(unlock()) |
是否支持條件變量 | 否 | 是 |
靈活性 | 低(簡單場景) | 高(復雜場景) |
性能 | 更高(輕量) | 稍低(有狀態) |
推薦場景 | 普通臨界區保護 | 條件變量、復雜鎖邏輯 |
優點總結
? 異常安全:即使臨界區拋出異常,鎖也會被釋放
? 自動管理:無需手動調用 unlock()
? 代碼簡潔:避免忘記解鎖
? 性能高:無額外開銷
適用場景限制
? 不能用于需要嘗試加鎖(try_lock)的場景
? 不能用于需要條件變量(std::condition_variable)的場景
? 不能用于需要遞歸加鎖的場景(除非使用 std::recursive_mutex)
總結
std::lock_guard 是 C++ 中最簡單、最安全的互斥鎖管理方式,應作為首選工具用于保護臨界區。只要你的場景是“進入作用域加鎖,離開作用域解鎖”,就使用 std::lock_guard。
💡 記住一句話:“加鎖后立即創建 lock_guard,讓它幫你管理鎖的生命周期。”
如果你需要更復雜的鎖控制(如等待條件、手動解鎖),再考慮使用 std::unique_lock。