C++ 線程互斥鎖 lock_guard的基本用法
std::lock_guard是 C++11 標(biāo)準(zhǔn)庫提供的RAII 風(fēng)格的互斥鎖封裝類,核心目的是自動管理互斥鎖的加鎖 / 解鎖,從根本上避免 “忘記解鎖導(dǎo)致死鎖”“異常導(dǎo)致鎖無法釋放” 這類低級且致命的錯誤。
一、先理解核心:RAII 設(shè)計(jì)思想
lock_guard的底層是RAII(資源獲取即初始化) 機(jī)制 —— 簡單說:
- 構(gòu)造時獲取資源:
lock_guard對象創(chuàng)建時,自動調(diào)用互斥鎖的lock()方法加鎖; - 析構(gòu)時釋放資源:
lock_guard對象銷毀時(比如出作用域),自動調(diào)用互斥鎖的unlock()方法解鎖。
這種 “自動性” 是解決多線程鎖管理問題的關(guān)鍵,不用再手動記著unlock()。
二、lock_guard的基本用法(對比手動加解鎖)
先看錯誤的手動加解鎖(容易出問題):
#include <mutex>
std::mutex mtx;
void wrong_func() {
mtx.lock(); // 手動加鎖
// 臨界區(qū)操作:修改共享資源
int a = 10;
// 忘記解鎖 → 死鎖!
// 或如果臨界區(qū)拋出異常,unlock()永遠(yuǎn)執(zhí)行不到 → 死鎖!
// mtx.unlock();
}再看正確的 lock_guard 用法(自動解鎖):
#include <mutex>
std::mutex mtx;
void right_func() {
// 創(chuàng)建lock_guard對象時,自動調(diào)用mtx.lock()
std::lock_guard<std::mutex> lock(mtx);
// 臨界區(qū):安全操作共享資源
int a = 10;
} // lock_guard對象出作用域,析構(gòu)時自動調(diào)用mtx.unlock()
// 即使臨界區(qū)拋出異常,析構(gòu)函數(shù)也會執(zhí)行 → 必解鎖!三、lock_guard的核心特性
1. 不可拷貝、不可移動
lock_guard被設(shè)計(jì)為 “只能在當(dāng)前作用域使用”,禁止拷貝 / 移動,避免鎖的管理權(quán)被非法轉(zhuǎn)移:
std::lock_guard<std::mutex> lock1(mtx); // std::lock_guard<std::mutex> lock2 = lock1; // 編譯錯誤:禁止拷貝 // std::lock_guard<std::mutex> lock3(std::move(lock1)); // 編譯錯誤:禁止移動
2. 作用域決定解鎖時機(jī)
lock_guard的解鎖時機(jī)完全由作用域控制,你可以通過{}手動限定作用域,精準(zhǔn)控制解鎖時機(jī):
void func() {
{
std::lock_guard<std::mutex> lock(mtx);
// 短臨界區(qū):只保護(hù)必要的代碼
shared_data = 100;
} // 此處提前解鎖,不影響后續(xù)非臨界區(qū)代碼
// 非臨界區(qū):無需持鎖,提升并發(fā)效率
sleep(1);
}3. 輕量級、無額外開銷
lock_guard是極簡封裝,沒有額外的成員函數(shù)(比如unlock()/lock()),運(yùn)行時幾乎無性能損耗,適合簡單的臨界區(qū)保護(hù)。
4. 異常安全
這是lock_guard最核心的優(yōu)勢之一:即使臨界區(qū)拋出異常,C++ 的異常機(jī)制會保證局部對象的析構(gòu)函數(shù)執(zhí)行,從而確保鎖被釋放:
void func_with_exception() {
std::lock_guard<std::mutex> lock(mtx);
// 臨界區(qū)拋出異常
throw std::runtime_error("出錯了");
// 無需手動unlock,析構(gòu)函數(shù)會處理
}
int main() {
try {
func_with_exception();
} catch (...) {
// 捕獲異常后,鎖已經(jīng)被釋放,其他線程可正常獲取
}
return 0;
}四、lock_guardvsunique_lock(選型參考)
lock_guard是 “輕量版” 鎖管理,std::unique_lock是 “功能版”,兩者的核心區(qū)別如下:
| 特性 | std::lock_guard | std::unique_lock |
|---|---|---|
| 自動加解鎖 | ? 支持 | ? 支持 |
手動解鎖(unlock()) | ? 不支持 | ? 支持 |
配合條件變量(cv.wait()) | ? 不支持 | ? 支持 |
| 性能 | 極致輕量 | 略重(有額外狀態(tài)) |
| 適用場景 | 簡單臨界區(qū)保護(hù) | 復(fù)雜同步(如條件變量、手動控制解鎖) |
簡單說:
- 只要是 “加鎖后,作用域結(jié)束解鎖” 的簡單場景,優(yōu)先用
lock_guard(輕量、高效); - 如果需要手動解鎖、配合條件變量(比如
cv.wait()需要解鎖后阻塞),用unique_lock。
五、完整示例:lock_guard 保護(hù)共享資源
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;
int shared_count = 0; // 共享資源
// 線程函數(shù):累加共享變量
void increment(int n) {
for (int i = 0; i < n; ++i) {
// lock_guard自動加鎖/解鎖
std::lock_guard<std::mutex> lock(mtx);
shared_count++;
// 出循環(huán)迭代的作用域,自動解鎖
}
}
int main() {
std::vector<std::thread> threads;
// 創(chuàng)建10個線程,每個線程累加1000次
for (int i = 0; i < 10; ++i) {
threads.emplace_back(increment, 1000);
}
// 等待所有線程結(jié)束
for (auto& t : threads) {
t.join();
}
// 正確輸出10000,無數(shù)據(jù)錯亂
std::cout << "最終count值:" << shared_count << std::endl;
return 0;
}總結(jié)
std::lock_guard是 C++11 的 RAII 鎖封裝,構(gòu)造加鎖、析構(gòu)解鎖,核心解決 “忘記解鎖 / 異常導(dǎo)致鎖泄漏” 的問題;- 輕量級、異常安全、不可拷貝,適合簡單臨界區(qū)的線程安全保護(hù);
- 解鎖時機(jī)由作用域決定,可通過
{}手動縮小作用域,提升并發(fā)效率; - 復(fù)雜同步場景(如條件變量)用
unique_lock,簡單場景優(yōu)先用lock_guard。
到此這篇關(guān)于C++ 線程互斥鎖 lock_guard的基本用法的文章就介紹到這了,更多相關(guān)C++ 線程互斥鎖 lock_guard內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV實(shí)現(xiàn)實(shí)時顏色檢測的示例
本文主要介紹了OpenCV實(shí)現(xiàn)實(shí)時顏色檢測的示例,通過HSV色彩空間轉(zhuǎn)換和色調(diào)范圍判斷實(shí)現(xiàn)紅黃綠藍(lán)顏色檢測,包含視頻捕捉、區(qū)域標(biāo)記、顏色分析等功能,具有一定的參考價值,感興趣的可以了解一下2025-06-06
C++實(shí)現(xiàn)LeetCode(7.翻轉(zhuǎn)整數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(7.翻轉(zhuǎn)整數(shù)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++?容器中map和unordered?map區(qū)別詳解
這篇文章主要為大家介紹了C++?容器中map和unordered?map區(qū)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
C++字符串和數(shù)字的去重操作和鞍點(diǎn)的尋找
大家好,本篇文章主要講的是C++字符串和數(shù)字的去重操作和鞍點(diǎn)的尋找,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
C/C++使用fmt庫實(shí)現(xiàn)格式化字符串
fmt庫是一個高效、易用的C++格式化庫,可以幫助我們方便地進(jìn)行字符串格式化、輸出、日志記錄等操作,下面我們就來學(xué)習(xí)一下fmt格式化字符串的具體操作吧2023-12-12
C++類與對象的重點(diǎn)知識點(diǎn)詳細(xì)分析
類和對象是兩種以計(jì)算機(jī)為載體的計(jì)算機(jī)語言的合稱。對象是對客觀事物的抽象,類是對對象的抽象。類是一種抽象的數(shù)據(jù)類型;變量就是可以變化的量,存儲在內(nèi)存中—個可以擁有在某個范圍內(nèi)的可變存儲區(qū)域2023-02-02

