最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++線程鎖的使用

 更新時間:2026年02月03日 09:50:41   作者:Ralph_Y  
C++提供了多種鎖機(jī)制,本文主要介紹了C++線程鎖的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、基礎(chǔ)概念:鎖的核心分類

在講解具體工具前,先明確C++鎖的兩個核心維度:

  1. 基礎(chǔ)鎖類型(提供原始的加鎖/解鎖能力):std::mutex、std::recursive_mutex、std::timed_mutex、std::recursive_timed_mutex;
  2. RAII鎖封裝(管理基礎(chǔ)鎖的生命周期,避免手動解鎖漏解/死鎖):std::lock_guard、std::unique_lock、std::scoped_lock(C++17)。

二、基礎(chǔ)鎖類型(原始鎖)

這類鎖是“底層同步工具”,提供lock()、unlock()、try_lock()等核心方法,但不建議直接使用(手動解鎖易出錯),需配合RAII封裝使用。

鎖類型核心特性適用場景注意事項(xiàng)
std::mutex最基礎(chǔ)的互斥鎖,非遞歸、非超時絕大多數(shù)單資源互斥場景同一線程重復(fù)lock()會觸發(fā)未定義行為(崩潰)
std::recursive_mutex遞歸互斥鎖,同一線程可多次lock()(需對應(yīng)次數(shù)unlock())函數(shù)嵌套調(diào)用需要加鎖的場景性能略低于std::mutex,避免濫用
std::timed_mutex帶超時的互斥鎖,支持try_lock_for()(超時時間)、try_lock_until()(截止時間)需要“非阻塞等待鎖”的場景超時返回false,避免永久阻塞
std::recursive_timed_mutex遞歸+超時的互斥鎖,結(jié)合前兩者特性遞歸調(diào)用+超時等待的場景盡量少用,遞歸鎖易隱藏邏輯問題

基礎(chǔ)鎖使用示例(不推薦直接用,僅演示)

#include <mutex>
#include <iostream>
std::mutex m;

void bad_use() {
    m.lock(); // 手動加鎖
    std::cout << "臨界區(qū)操作" << std::endl;
    // 若此處拋異常,unlock()不會執(zhí)行 → 死鎖!
    m.unlock(); // 手動解鎖
}

核心問題:手動管理lock()/unlock()易因異常、邏輯分支遺漏解鎖,導(dǎo)致死鎖——這也是RAII封裝的核心價值。

三、RAII鎖封裝(推薦使用)

RAII(資源獲取即初始化)的核心思想:構(gòu)造時獲取資源,析構(gòu)時釋放資源。鎖封裝會在構(gòu)造函數(shù)中調(diào)用lock()(或接管已鎖定的鎖),析構(gòu)函數(shù)中調(diào)用unlock(),無論函數(shù)正常退出還是異常退出,鎖都會被釋放。

1. std::lock_guard(極簡RAII鎖,C++11)

核心特性
  • 不可移動、不可復(fù)制,生命周期與作用域綁定;
  • 構(gòu)造時必須指定鎖,且默認(rèn)立即加鎖
  • 析構(gòu)時自動解鎖,無其他額外功能(極簡、高效);
  • 不支持手動解鎖、不支持超時、不支持延遲加鎖。

使用示例(最常用場景)

#include <mutex>
#include <list>
std::list<int> data;
std::mutex m;

void safe_add(int val) {
    // 構(gòu)造時加鎖,函數(shù)結(jié)束析構(gòu)時解鎖
    std::lock_guard<std::mutex> guard(m);
    data.push_back(val); // 臨界區(qū)操作,線程安全
}

進(jìn)階用法:接管已鎖定的鎖(std::adopt_lock)

當(dāng)鎖已被std::lock()手動鎖定時,用std::adopt_lock標(biāo)記告訴lock_guard“鎖已鎖定,只需接管解鎖責(zé)任”:

void swap_data(std::list<int>& a, std::list<int>& b, std::mutex& m1, std::mutex& m2) {
    if (&a == &b) return;
    std::lock(m1, m2); // 同時鎖定兩個鎖,避免死鎖
    // adopt_lock:不重復(fù)加鎖,僅接管解鎖
    std::lock_guard<std::mutex> g1(m1, std::adopt_lock);
    std::lock_guard<std::mutex> g2(m2, std::adopt_lock);
    a.swap(b); // 臨界區(qū)操作
}

適用場景

  • 簡單的“作用域內(nèi)加鎖”場景,無需手動控制鎖的生命周期;
  • 追求極致性能(無額外開銷),只需“加鎖→操作→解鎖”的固定流程。

2. std::unique_lock(靈活RAII鎖,C++11)

核心特性

  • 不可復(fù)制、可移動,生命周期可手動控制;
  • 支持延遲加鎖(構(gòu)造時不加鎖,后續(xù)手動lock());
  • 支持手動解鎖(unlock())、重新加鎖(lock());
  • 支持超時加鎖(try_lock_for()、try_lock_until(),需配合timed_mutex);
  • 支持std::adopt_lock接管已鎖定的鎖;
  • 性能略高于lock_guard(但可忽略),功能遠(yuǎn)更靈活。

核心用法示例

(1)延遲加鎖(std::defer_lock)

#include <mutex>
std::timed_mutex tm;

void flexible_lock() {
    // defer_lock:構(gòu)造時不加鎖,僅關(guān)聯(lián)鎖對象
    std::unique_lock<std::timed_mutex> ul(tm, std::defer_lock);
    
    // 手動加鎖(也可嘗試超時加鎖)
    if (ul.try_lock_for(std::chrono::seconds(1))) {
        std::cout << "獲取鎖成功,執(zhí)行臨界區(qū)操作" << std::endl;
        ul.unlock(); // 手動解鎖(可提前釋放鎖,提高并發(fā))
        // ... 其他非臨界區(qū)操作
        ul.lock(); // 重新加鎖
    } else {
        std::cout << "1秒內(nèi)未獲取鎖,執(zhí)行降級邏輯" << std::endl;
    }
    // 析構(gòu)時:如果鎖仍被持有,自動解鎖
}

(2)配合條件變量(唯一適用場景)

std::condition_variablewait()方法必須接收std::unique_lock(因?yàn)?code>wait()會臨時解鎖,被喚醒后重新加鎖,lock_guard無此能力):

#include <mutex>
#include <condition_variable>
#include <queue>

std::queue<int> q;
std::mutex m;
std::condition_variable cv;

void producer(int val) {
    std::lock_guard<std::mutex> lg(m);
    q.push(val);
    cv.notify_one(); // 通知消費(fèi)者
}

void consumer() {
    std::unique_lock<std::mutex> ul(m);
    // wait()會解鎖,等待通知;被喚醒后重新加鎖,再判斷條件
    cv.wait(ul, [](){ return !q.empty(); });
    int val = q.front();
    q.pop();
    ul.unlock(); // 提前解鎖,提高并發(fā)
    std::cout << "消費(fèi):" << val << std::endl;
}

適用場景

  • 需要手動控制鎖的生命周期(提前解鎖、重新加鎖);
  • 需要超時等待鎖的場景;
  • 配合std::condition_variable使用(唯一選擇);
  • 復(fù)雜的加鎖邏輯(如條件加鎖、動態(tài)解鎖)。

3. std::scoped_lock(C++17,lock_guard的升級版)

核心特性

  • 不可移動、不可復(fù)制,作用域綁定;
  • 支持同時鎖定多個鎖(內(nèi)置std::lock()的死鎖避免邏輯);
  • 性能與lock_guard一致,語法更簡潔;
  • 可視為“多鎖版本的lock_guard”。

使用示例(替代lock_guard+std::lock)

#include <mutex>
#include <list>

std::list<int> a, b;
std::mutex m1, m2;

void safe_swap() {
    // 同時鎖定m1和m2,自動避免死鎖,析構(gòu)時同時解鎖
    std::scoped_lock guard(m1, m2);
    a.swap(b); // 臨界區(qū)操作
}

對比舊寫法(lock_guard+std::lock):

std::lock(m1, m2);
std::lock_guard<std::mutex> g1(m1, std::adopt_lock);
std::lock_guard<std::mutex> g2(m2, std::adopt_lock);

scoped_lock一行搞定,更簡潔、不易出錯。

適用場景

  • 需要同時鎖定多個鎖的場景(替代std::lock + lock_guard);
  • C++17及以上環(huán)境,優(yōu)先選擇scoped_lock而非lock_guard(功能更強(qiáng),無性能損失)。

四、其他鎖相關(guān)工具

1. std::call_once(單次調(diào)用鎖)

  • 核心作用:保證某個函數(shù)在多線程環(huán)境下僅執(zhí)行一次(比如單例的初始化);
  • 底層依賴std::once_flag,比手動加鎖判斷更高效、更安全。

使用示例

#include <mutex>
#include <iostream>

std::once_flag flag;
void init() {
    std::cout << "僅執(zhí)行一次的初始化邏輯" << std::endl;
}

void thread_func() {
    std::call_once(flag, init); // 多線程調(diào)用,init僅執(zhí)行一次
}

2. std::shared_mutex / std::shared_lock(C++17,讀寫鎖)

  • 核心思想:區(qū)分“讀操作”和“寫操作”,允許多個讀線程同時持有鎖,寫線程獨(dú)占鎖(提高讀多寫少場景的并發(fā));
    • std::shared_lock:共享鎖(讀鎖),多個線程可同時持有;
    • std::unique_lock:獨(dú)占鎖(寫鎖),僅一個線程持有。

使用示例

#include <shared_mutex>
#include <string>
#include <iostream>

std::string data = "初始數(shù)據(jù)";
std::shared_mutex sm;

// 讀線程:共享鎖
void read_data(int id) {
    std::shared_lock<std::shared_mutex> sl(sm);
    std::cout << "讀線程" << id << ":" << data << std::endl;
}

// 寫線程:獨(dú)占鎖
void write_data(const std::string& new_data) {
    std::unique_lock<std::shared_mutex> ul(sm);
    data = new_data;
    std::cout << "寫線程:更新數(shù)據(jù)為" << new_data << std::endl;
}

優(yōu)勢:讀多寫少場景下,并發(fā)效率遠(yuǎn)高于普通互斥鎖(普通鎖無論讀寫都獨(dú)占)。

3. std::lock(通用鎖函數(shù))

  • 核心作用:原子地鎖定多個鎖,避免死鎖(內(nèi)部實(shí)現(xiàn)按地址排序鎖定);
  • 配合lock_guard/unique_lock的adopt_lock使用(C++17前);
  • C++17后優(yōu)先用scoped_lock,無需手動調(diào)用std::lock。

五、核心對比與選型建議

工具核心優(yōu)勢核心限制優(yōu)先選型場景
std::lock_guard極簡、高效不可手動解鎖、不支持多鎖C++11/14,單鎖、簡單作用域加鎖
std::unique_lock靈活(延遲/超時/手動解鎖)略高開銷(可忽略)條件變量、超時等待、動態(tài)解鎖
std::scoped_lock多鎖、簡潔、高效C++17+C++17+,單鎖/多鎖、所有簡單場景
std::shared_mutex讀寫分離,讀多寫少并發(fā)高C++17+讀多寫少的共享資源訪問
std::call_once單次調(diào)用,無需手動加鎖判斷僅單次執(zhí)行初始化、單例創(chuàng)建

選型口訣

  1. C++17及以上:優(yōu)先用scoped_lock(單鎖/多鎖),復(fù)雜邏輯用unique_lock;
  2. C++11/14:單鎖用lock_guard,多鎖用std::lock + lock_guard,復(fù)雜邏輯用unique_lock;
  3. 讀多寫少:用std::shared_mutex + shared_lock/unique_lock;
  4. 單次初始化:用std::call_once;
  5. 條件變量:必須用unique_lock。

六、總結(jié)

  1. 基礎(chǔ)鎖:std::mutex是核心,遞歸場景用recursive_mutex,超時場景用timed_mutex;
  2. RAII封裝:
    • 簡單場景:lock_guard(C++11/14)/scoped_lock(C++17+);
    • 復(fù)雜場景:unique_lock(靈活、支持條件變量/超時);
  3. 特殊場景:
    • 讀多寫少:shared_mutex + shared_lock;
    • 單次執(zhí)行:call_once;
  4. 核心原則:永遠(yuǎn)用RAII封裝管理鎖,避免手動lock()/unlock(),防止死鎖。

到此這篇關(guān)于C++線程鎖的使用的文章就介紹到這了,更多相關(guān)C++線程鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

禹城市| 安徽省| 卫辉市| 禹城市| 汶上县| 深州市| 台安县| 扎兰屯市| 泗水县| 图们市| 尚义县| 兴宁市| 扶沟县| 枣强县| 盐津县| 翁牛特旗| 台中县| 六盘水市| 惠安县| 宁蒗| 红桥区| 佛教| 高要市| 宜兰市| 德令哈市| 石渠县| 达拉特旗| 会理县| 文成县| 长沙县| 互助| 佛山市| 汉源县| 绥江县| 古丈县| 凭祥市| 政和县| 于田县| 五峰| 富锦市| 垣曲县|