【C++】互斥鎖(Mutex)

在C++中,互斥鎖(Mutex)是用于線程同步的重要工具,用于保護共享資源,防止多線程同時訪問導致的數據競爭(Data Race)問題。
以下是C++中互斥鎖的核心用法和示例:

一、基本互斥鎖 std::mutex

1. 包含頭文件
#include <mutex>
2. 保護共享資源
std::mutex mtx;  // 聲明互斥鎖
int shared_data = 0;  // 共享資源void increment() {mtx.lock();      // 加鎖++shared_data;   // 臨界區mtx.unlock();    // 解鎖
}
3. 使用 std::lock_guard 自動管理鎖
void safe_increment() {std::lock_guard<std::mutex> lock(mtx);  // 構造時加鎖,析構時解鎖++shared_data;                          // 自動保護臨界區
}  // 離開作用域時鎖自動釋放

二、遞歸互斥鎖 std::recursive_mutex

允許同一線程多次加鎖,避免死鎖:

std::recursive_mutex rmtx;void func1() {std::lock_guard<std::recursive_mutex> lock(rmtx);// 可以在此處再次加鎖func2();
}void func2() {std::lock_guard<std::recursive_mutex> lock(rmtx);  // 同一線程可重入// ...
}

三、帶超時的互斥鎖 std::timed_mutex

std::timed_mutex tmtx;void try_lock_with_timeout() {// 嘗試加鎖,超時則放棄if (tmtx.try_lock_for(std::chrono::milliseconds(100))) {// 加鎖成功tmtx.unlock();} else {// 加鎖失敗}
}

四、讀寫鎖 std::shared_mutex(C++17)

允許多個線程同時讀,但寫時獨占:

#include <shared_mutex>  // C++17std::shared_mutex rw_mutex;
std::string shared_data;// 讀操作(共享鎖)
void reader() {std::shared_lock<std::shared_mutex> lock(rw_mutex);// 允許多個讀者同時訪問std::cout << shared_data << std::endl;
}// 寫操作(獨占鎖)
void writer() {std::unique_lock<std::shared_mutex> lock(rw_mutex);// 獨占訪問shared_data = "new data";
}

五、鎖的高級用法

1. 避免死鎖:使用 std::lock 同時鎖多個互斥鎖
std::mutex mtx1, mtx2;void safe_func() {// 原子性地鎖多個互斥鎖,避免死鎖std::lock(mtx1, mtx2);std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);// ...
}
2. 延遲加鎖 std::defer_lock
std::mutex mtx;void defer_lock_example() {std::unique_lock<std::mutex> lock(mtx, std::defer_lock);// 此時尚未加鎖// ...lock.lock();  // 手動加鎖// ...
}

六、常見錯誤與注意事項

  1. 忘記解鎖
    使用 std::lock_guardstd::unique_lock 自動管理鎖,避免手動 lock/unlock

  2. 鎖粒度不當

    • 過大:性能下降(如鎖整個函數)。
    • 過小:無法保護共享資源。
  3. 死鎖風險

    • 避免嵌套鎖。
    • 確保所有線程以相同順序加鎖。
  4. 性能考量

    • 讀寫鎖(std::shared_mutex)適合讀多寫少的場景。
    • 無鎖編程(Lock-Free)技術在高性能場景中更優。

七、示例:線程安全的計數器

#include <mutex>
#include <thread>
#include <iostream>class Counter {
private:int value = 0;std::mutex mtx;public:void increment() {std::lock_guard<std::mutex> lock(mtx);++value;}int get() {std::lock_guard<std::mutex> lock(mtx);return value;}
};int main() {Counter counter;std::thread t1([&]() {for (int i = 0; i < 10000; ++i) {counter.increment();}});std::thread t2([&]() {for (int i = 0; i < 10000; ++i) {counter.increment();}});t1.join();t2.join();std::cout << "Final value: " << counter.get() << std::endl;  // 輸出:20000return 0;
}

八、C++ 互斥鎖類型對比

類型特性適用場景
std::mutex基本互斥鎖,不可重入簡單互斥場景
std::recursive_mutex可重入鎖,允許同一線程多次加鎖遞歸函數或嵌套鎖場景
std::timed_mutex支持超時的互斥鎖需要嘗試加鎖并設置超時的場景
std::shared_mutex讀寫鎖,允許多讀一寫讀多寫少的場景

合理選擇互斥鎖類型能有效提升代碼的安全性和性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79742.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79742.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79742.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jsoup與HtmlUnit:兩大Java爬蟲工具對比解析

Jsoup&#xff1a;HTML解析利器 定位&#xff1a;專注HTML解析的輕量級庫&#xff08;也就是快&#xff0c;但動態頁面無法抓取&#xff09; 核心能力&#xff1a; DOM樹解析與CSS選擇器查詢 HTML凈化與格式化 支持元素遍歷與屬性提取 應用場景&#xff1a;靜態頁面數據抽…

小白成長之路-vim編輯

文章目錄 Vim一、命令模式二、插入模式3.a:進入插入模式&#xff0c;在當前光標的后一個字符插入![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/fd293c3832ed49e2974abfbb63eeb5bb.png)4.o: 在當前光標的下一行插入5.i:在當前光標所在字符插入&#xff0c;返回命令模…

[redis進階六]詳解redis作為緩存分布式鎖

目錄 一 什么是緩存 緩存總結板書: 二 使?Redis作為緩存 三 緩存的更新策略 1) 定期?成 2) 實時?成 四 面試重點:緩存預熱,緩存穿透,緩存雪崩 和緩存擊穿 1)緩存預熱 2)緩存穿透 3)緩存雪崩 4)緩存擊穿 五 分布式鎖 板書: 1)什么是分布式鎖 2)分布式鎖的基…

【MySQL】數據表插入數據

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;MySQL 文章目錄 1. 插入數據概述1.1 插入數據的重要性1.2 插入數據的基本原則 2. 基本插入語句2.1 INSERT INTO語法2.2 插入多行數據2.3 不指定列名的插入2.4 插入NULL和默認值 3. 高級插入技術3.1 使用子查詢插入數據3.2 IGNOR…

軟考-軟件設計師中級備考 14、刷題 算法

一、考點歸納 1&#xff09;排序 2、查找 3、復雜度 4、經典問題 0 - 1 背包動態規劃0 - 1 背包問題具有最優子結構性質和重疊子問題性質。通過動態規劃可以利用一個二維數組來記錄子問題的解&#xff0c;避免重復計算&#xff0c;從而高效地求解出背包能裝下的最大價值。分…

【阿里云】阿里云 Ubuntu 服務器無法更新 systemd(Operation not permitted)的解決方法

零、前言 目前正在使用的Ubuntu服務器中&#xff0c;僅阿里云&#xff08;不止一臺&#xff09;出現了這個問題&#xff0c;因此我判定是阿里云服務器獨有的問題。如果你的服務器提供商不是阿里云&#xff0c;那么這篇文章可能對你沒有幫助。 如果已經因為升級錯誤導致依賴沖突…

css 點擊后改變樣式

背景&#xff1a; 期望實現效果&#xff1a;鼠標點擊之后&#xff0c;保持選中樣式。 實現思路&#xff1a;在css樣式中&#xff0c;:active 是一種偽類&#xff0c;用于表示用戶當前正在與被選定的元素進行交互。當用戶點擊或按住鼠標時&#xff0c;元素將被激活&#xff0c;此…

采用AI神經網絡降噪算法的語言降噪消回音處理芯片NR2049-P

隨著AI時代來臨.通話設備的環境噪音抑制也進入AI降噪算法時代. AI神經網絡降噪技術是一款革命性的語音處理技術&#xff0c;他突破了傳統單麥克風和雙麥克風降噪的局限性,利用采集的各種日常環境中的噪音樣本進行訓練學習.讓降噪算法具有自適應噪聲抑制功能&#xff0c;可以根…

不用聯網不用編程,PLC通過智能網關快速實現HTTP協議JSON格式與MES等系統平臺雙向數據通訊

智能網關IGT-DSER集成了多種PLC的原廠協議&#xff0c;方便實現各種PLC、智能儀表通過HTTP協議與MES等各種系統平臺通訊對接。PLC內不用編寫程序&#xff0c;設備不用停機&#xff0c;通過網關的參數配置軟件(下載地址)配置JSON文件的字段與PLC寄存器地址等參數即可。 …

如何將兩臺虛擬機進行搭橋

將兩臺虛擬機實現網絡互通&#xff08;“搭橋”&#xff09;需配置虛擬網絡&#xff0c;以下是基于 VMware Workstation 和 VirtualBox 的詳細操作指南&#xff08;以 Windows 系統為例&#xff0c;Linux 原理類似&#xff09;&#xff1a; 一、VMware Workstation 配置&#x…

Xianyu AutoAgent,AI閑魚客服機器人

Xianyu AutoAgent是一款專為閑魚平臺開發的智能客服機器人系統&#xff0c;旨在提供全天候的自動化服務。它具備多專家協同決策、智能議價和上下文感知對話等功能&#xff0c;能夠管理輕量級的對話記憶&#xff0c;利用完整的對話歷史為用戶提供更自然的交流體驗。 Xianyu Aut…

鍵盤輸出希臘字符方法

在不同操作系統中&#xff0c;輸出希臘字母的方法有所不同。以下是針對 Windows 和 macOS 系統的詳細方法&#xff0c;以及一些通用技巧&#xff1a; 1.Windows 系統 1.1 使用字符映射表 字符映射表是一個內置工具&#xff0c;可以方便地找到并插入希臘字母。 ? 步驟&#xf…

什么是SparkONYarn模式

1. 什么是 Spark on YARN&#xff1f; Spark on YARN 是 Apache Spark 的一種部署模式&#xff0c;允許 Spark 應用程序在 Hadoop YARN 集群上運行&#xff0c;充分利用 YARN 的資源管理和調度能力。這種模式將 Spark 與 Hadoop 生態深度集成&#xff0c;使企業能夠在同一集群…

【git】clone項目后續,github clone的網絡配置,大型項目git log 輸出txt,切換commit學習,goland遠程,自存檔

git網絡配置&#xff0c;解決git clone github速度奇慢 git config --global http.proxy http://127.0.0.1:7897 git config --global https.proxy http://127.0.0.1:7897git log輸出到文件&#xff08;便于checkout&#xff09; 這里有些字符如表情會亂碼&#xff0c;不知道…

Java游戲服務器開發流水賬(3)游戲數據的緩存簡介

簡介 游戲服務器數據緩存是一種在游戲服務器運行過程中&#xff0c;用于臨時存儲經常訪問的數據的技術手段&#xff0c;旨在提高游戲性能、降低數據庫負載以及優化玩家體驗。游戲開發中數據的緩存可以使用Java自身的內存也可以使用MemCache&#xff0c;Redis&#xff0c;注意M…

STL?vector!!!

一、前言 之前我們借助手撕string加深了類和對象相關知識&#xff0c;今天我們將一起手撕一個vector&#xff0c;繼續深化類和對象、動態內存管理、模板的相關知識 二、vector相關的前置知識 1、什么是vector&#xff1f; vector是一個STL庫中提供的類模板&#xff0c;它是存儲…

C++學習之路,從0到精通的征途:繼承

目錄 一.繼承的概念及定義 1.繼承的概念 2.繼承的定義 (1)繼承的定義格式 (2)繼承基類成員訪問方式的變化 二.基類與派生類間的轉換 1.派生類對象賦值給基類的引用/指針 2. 派生類對象直接賦值給基類對象 三.繼承的作用域 四.派生類的默認成員函數 1.構造函數 2.拷…

用vue和go實現登錄加密

前端使用CryptoJS默認加密方法&#xff1a; var pass CryptoJS.AES.encrypt(formData.password, key.value).toString()使用 CryptoJS.AES.encrypt() 時不指定加密模式和參數時&#xff0c;CryptoJS 默認會執行以下操作 var encrypted CryptoJS.AES.encrypt("明文&quo…

React百日學習計劃——Deepseek版

階段一&#xff1a;基礎鞏固&#xff08;1-20天&#xff09; 目標&#xff1a;掌握HTML/CSS/JavaScript核心語法和開發環境搭建。 每日學習內容&#xff1a; HTML/CSS&#xff08;1-10天&#xff09; 標簽語義化、盒模型、Flex布局、Grid布局、響應式設計&#xff08;媒體查詢…

WPF中如何自定義控件

WPF自定義控件簡化版&#xff1a;賬戶菜單按鈕&#xff08;AccountButton&#xff09; 我們以**“賬戶菜單按鈕”為例&#xff0c;用更清晰的架構實現一個支持標題顯示、漸變背景、選中狀態高亮**的自定義控件。以下是分步拆解&#xff1a; 一、控件核心功能 我們要做一個類似…