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

C++ 多線程同步之互斥鎖(mutex)實(shí)戰(zhàn)指南

 更新時間:2026年05月18日 11:06:22   作者:小林說AI  
本文介紹了C++標(biāo)準(zhǔn)庫中互斥鎖的基本用法,主要了std::mutex與std::lock_guard的使用方法,解釋了死鎖的產(chǎn)生原因及規(guī)避方法,并通過實(shí)際案例展示了如何解決多線程環(huán)境下的資源競爭問題,感興趣的朋友一起看看吧

?? 學(xué)習(xí)目標(biāo):掌握 C++ 標(biāo)準(zhǔn)庫中互斥鎖的基本用法,理解多線程同步的核心原理,能夠解決多線程環(huán)境下的資源競爭問題。
?? 學(xué)習(xí)重點(diǎn)std::mutexstd::lock_guard 的使用、死鎖的產(chǎn)生原因及規(guī)避方法、實(shí)際場景中的同步案例實(shí)現(xiàn)。

48.1 多線程同步的必要性

在多線程編程中,當(dāng)多個線程同時訪問共享資源時,會出現(xiàn)資源競爭問題。
例如兩個線程同時對同一個變量進(jìn)行讀寫操作,會導(dǎo)致最終結(jié)果與預(yù)期不符。
這種問題被稱為線程安全問題,而解決該問題的核心就是線程同步。

?? 注意事項(xiàng):線程不同步會引發(fā)數(shù)據(jù)競爭,造成程序運(yùn)行結(jié)果不可預(yù)測,甚至導(dǎo)致程序崩潰。

舉個簡單的反例,兩個線程同時對全局變量 count 進(jìn)行自增操作:

#include <iostream>
#include <thread>
using namespace std;
int count = 0;
void increment() {
    for (int i = 0; i < 100000; ++i) {
        count++; // 非原子操作,存在數(shù)據(jù)競爭
    }
}
int main() {
    thread t1(increment);
    thread t2(increment);
    t1.join();
    t2.join();
    cout << "最終 count 值:" << count << endl;
    return 0;
}

運(yùn)行該程序會發(fā)現(xiàn),最終 count 的值大概率小于 200000。
這就是因?yàn)?count++ 不是原子操作,被兩個線程交替執(zhí)行打亂了執(zhí)行步驟。

48.2 C++ 標(biāo)準(zhǔn)庫中的互斥鎖

C++11 及以后的標(biāo)準(zhǔn)庫提供了 <mutex> 頭文件,封裝了多種互斥鎖相關(guān)的類。
最基礎(chǔ)且常用的就是 std::mutex

48.2.1std::mutex的核心接口

  • lock():獲取互斥鎖。如果鎖已被其他線程占用,當(dāng)前線程會阻塞等待。
  • unlock():釋放互斥鎖。必須與 lock() 成對使用。
  • try_lock():嘗試獲取互斥鎖。如果獲取失敗,不會阻塞,直接返回 false。

48.2.2std::lock_guard:自動管理鎖的生命周期

直接使用 lock()unlock() 容易出現(xiàn)遺漏解鎖的情況。
比如程序拋出異常時,unlock() 可能無法執(zhí)行,導(dǎo)致死鎖。
std::lock_guard 基于RAII 機(jī)制實(shí)現(xiàn),可以自動在構(gòu)造時加鎖,析構(gòu)時解鎖。

? 核心結(jié)論:實(shí)際開發(fā)中優(yōu)先使用 std::lock_guard,而非手動調(diào)用 lock()/unlock()

48.3 互斥鎖實(shí)戰(zhàn):解決數(shù)據(jù)競爭問題

我們使用 std::mutexstd::lock_guard 改造 48.1 節(jié)的反例:

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int count = 0;
mutex mtx; // 定義全局互斥鎖
void increment() {
    for (int i = 0; i < 100000; ++i) {
        lock_guard<mutex> lock(mtx); // 自動加鎖
        count++; // 臨界區(qū)代碼,此時只有一個線程能執(zhí)行
    } // lock_guard 析構(gòu),自動解鎖
}
int main() {
    thread t1(increment);
    thread t2(increment);
    t1.join();
    t2.join();
    cout << "最終 count 值:" << count << endl;
    return 0;
}

運(yùn)行該程序,最終 count 的值穩(wěn)定等于 200000。
這說明互斥鎖成功保護(hù)了臨界區(qū)代碼,避免了數(shù)據(jù)競爭。

48.3.1 關(guān)鍵概念解釋

  • 臨界區(qū):需要被保護(hù)的、不能被多個線程同時執(zhí)行的代碼段。
    上例中 count++ 就是臨界區(qū)。
  • 互斥鎖的作用:保證同一時刻只有一個線程能進(jìn)入臨界區(qū)。

48.4 死鎖的產(chǎn)生與規(guī)避

?? 死鎖:多個線程互相持有對方需要的鎖,導(dǎo)致所有線程都無法繼續(xù)執(zhí)行的狀態(tài)。

48.4.1 死鎖的四個必要條件

  1. 互斥條件:資源只能被一個線程占用。
  2. 請求與保持條件:線程持有一個資源的同時,請求其他線程持有的資源。
  3. 不可剝奪條件:線程已持有的資源不能被其他線程強(qiáng)制奪走。
  4. 循環(huán)等待條件:多個線程形成首尾相接的循環(huán)等待資源關(guān)系。

48.4.2 死鎖的示例

兩個線程分別持有一個鎖,同時請求對方的鎖:

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mtx1, mtx2;
void thread1() {
    mtx1.lock();
    this_thread::sleep_for(chrono::milliseconds(100)); // 確保 thread2 先拿到 mtx2
    mtx2.lock(); // 等待 mtx2,此時 thread2 持有 mtx2 并等待 mtx1
    cout << "thread1 執(zhí)行完畢" << endl;
    mtx2.unlock();
    mtx1.unlock();
}
void thread2() {
    mtx2.lock();
    this_thread::sleep_for(chrono::milliseconds(100)); // 確保 thread1 先拿到 mtx1
    mtx1.lock(); // 等待 mtx1,此時 thread1 持有 mtx1 并等待 mtx2
    cout << "thread2 執(zhí)行完畢" << endl;
    mtx1.unlock();
    mtx2.unlock();
}
int main() {
    thread t1(thread1);
    thread t2(thread2);
    t1.join();
    t2.join();
    return 0;
}

運(yùn)行該程序,兩個線程會互相等待,陷入死鎖狀態(tài),無法輸出任何內(nèi)容。

48.4.3 規(guī)避死鎖的常用方法

  1. 固定鎖的獲取順序:所有線程按照相同的順序獲取鎖。
    比如上例中,讓兩個線程都先獲取 mtx1,再獲取 mtx2
  2. 使用 std::lock 同時獲取多個鎖:std::lock 可以一次性獲取多個互斥鎖,避免循環(huán)等待。
  3. 使用帶超時的鎖嘗試:通過 try_lock()std::timed_mutex,在超時后放棄獲取鎖,避免永久阻塞。

48.5 實(shí)戰(zhàn)案例:多線程售票系統(tǒng)

模擬一個售票系統(tǒng),多個窗口同時售票,使用互斥鎖保證票數(shù)不會出現(xiàn)負(fù)數(shù)或重復(fù)售票的情況。

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
using namespace std;
int tickets = 100; // 總票數(shù)
mutex mtx;
// 售票函數(shù)
void sell_tickets(int window_id) {
    while (true) {
        lock_guard<mutex> lock(mtx);
        if (tickets > 0) {
            cout << "窗口" << window_id << "售出第" << tickets << "張票" << endl;
            tickets--;
            this_thread::sleep_for(chrono::milliseconds(50)); // 模擬售票耗時
        } else {
            break;
        }
    }
    cout << "窗口" << window_id << "售票結(jié)束" << endl;
}
int main() {
    vector<thread> windows;
    // 創(chuàng)建 5 個售票窗口
    for (int i = 1; i <= 5; ++i) {
        windows.emplace_back(sell_tickets, i);
    }
    // 等待所有窗口售票結(jié)束
    for (auto& t : windows) {
        t.join();
    }
    cout << "所有票已售罄" << endl;
    return 0;
}

? 運(yùn)行效果:5 個窗口有序售票,最終票數(shù)從 100 遞減到 0,不會出現(xiàn)重復(fù)售票或票數(shù)為負(fù)的情況。

48.6 本章小結(jié)

  1. 多線程訪問共享資源時必須進(jìn)行同步,否則會出現(xiàn)數(shù)據(jù)競爭問題。
  2. std::mutex 是 C++ 最基礎(chǔ)的互斥鎖,搭配 std::lock_guard 可以安全地管理鎖的生命周期。
  3. 死鎖由四個必要條件引發(fā),通過固定鎖順序、使用 std::lock 等方法可以有效規(guī)避。
  4. 互斥鎖的核心是保護(hù)臨界區(qū),確保同一時刻只有一個線程能執(zhí)行臨界區(qū)代碼。

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

相關(guān)文章

  • C++STL之vector模板類詳解

    C++STL之vector模板類詳解

    這篇文章主要為大家詳細(xì)介紹了C++vector模板類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++通過自定義函數(shù)求一元二次方程的根

    C++通過自定義函數(shù)求一元二次方程的根

    這篇文章主要介紹了C++通過自定義函數(shù)求一元二次方程的根,涉及C++數(shù)學(xué)運(yùn)算相關(guān)技巧,非常簡單實(shí)用,需要的朋友可以參考下
    2016-05-05
  • C語言數(shù)據(jù)結(jié)構(gòu)的時間復(fù)雜度和空間復(fù)雜度

    C語言數(shù)據(jù)結(jié)構(gòu)的時間復(fù)雜度和空間復(fù)雜度

    算法在編寫成可執(zhí)行程序后,運(yùn)行時需要耗費(fèi)時間資源和空間(內(nèi)存)資源 。因此衡量一個算法的好壞,一般是從時間和空間兩個維度來衡量的,即時間復(fù)雜度和空間復(fù)雜度,感興趣的同學(xué)可以參考閱讀
    2023-04-04
  • C++實(shí)現(xiàn)LeetCode(160.求兩個鏈表的交點(diǎn))

    C++實(shí)現(xiàn)LeetCode(160.求兩個鏈表的交點(diǎn))

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(160.求兩個鏈表的交點(diǎn)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C/C++中OpenCV 矩陣運(yùn)算的實(shí)現(xiàn)

    C/C++中OpenCV 矩陣運(yùn)算的實(shí)現(xiàn)

    本文主要介紹了C/C++中OpenCV 矩陣運(yùn)算的實(shí)現(xiàn),包括基本算術(shù)運(yùn)算(標(biāo)量與矩陣)、矩陣乘法、轉(zhuǎn)置、逆矩陣、行列式、跡、范數(shù)等操作,感興趣的可以了解一下
    2025-05-05
  • 解決在Mac下直接解壓C++靜態(tài)庫出現(xiàn)的問題

    解決在Mac下直接解壓C++靜態(tài)庫出現(xiàn)的問題

    最近在研究C++的各種編譯構(gòu)建過程,學(xué)習(xí)了一下cmake,gyp/ninja這些自動化構(gòu)建工具后,想著自己試下用純命令行跑一遍編譯流程。在試圖把C++靜態(tài)庫編譯為動態(tài)庫的過程中遇到了棘手的問題,找了好久后發(fā)現(xiàn)是跟Mac平臺相關(guān)的,這里記錄一下,望對遇到類似問題的童鞋有幫助。
    2016-12-12
  • 字符串的組合算法問題的C語言實(shí)現(xiàn)攻略

    字符串的組合算法問題的C語言實(shí)現(xiàn)攻略

    這篇文章主要介紹了字符串的組合算法問題的C語言實(shí)現(xiàn)攻略,是根據(jù)ACM總結(jié)的經(jīng)典算法問題,需要的朋友可以參考下
    2015-08-08
  • c++程序字符型的實(shí)例講解

    c++程序字符型的實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于
    2020-02-02
  • Qt使用SQLite數(shù)據(jù)庫實(shí)現(xiàn)數(shù)據(jù)增刪改查

    Qt使用SQLite數(shù)據(jù)庫實(shí)現(xiàn)數(shù)據(jù)增刪改查

    這篇文章主要為大家詳細(xì)介紹了Qt如何使用SQLite數(shù)據(jù)庫實(shí)現(xiàn)數(shù)據(jù)增刪改查功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-06-06
  • C指針原理教程之Ncurses介紹

    C指針原理教程之Ncurses介紹

    Ncurses 提供字符終端處理庫,包括面板和菜單。為了能夠使用ncurses庫,您必須在您的源程序中將curses.h包括(include)進(jìn)來,而且在編譯的需要與它連接起來. 在gcc中您可以使用參數(shù)-lcurses進(jìn)行編譯.
    2019-02-02

最新評論

多伦县| 贵定县| 琼海市| 岳阳市| 石狮市| 垣曲县| 合肥市| 徐水县| 二手房| 麟游县| 邵阳市| 闸北区| 建始县| 全南县| 柏乡县| 中卫市| 当雄县| 泰兴市| 东平县| 华容县| 沙田区| 北票市| 绥滨县| 大英县| 密云县| 卢湾区| 黄浦区| 喀什市| 定结县| 万载县| 新沂市| 紫金县| 梁河县| 罗江县| 仪陇县| 那曲县| 甘谷县| 巴青县| 青田县| 公安县| 东辽县|