C++標準庫中各種互斥鎖的用法 mutex

示例

僅供參考學習

#include <mutex>
#include <shared_mutex>
#include <thread>
#include <chrono>
#include <iostream>
#include <vector>// ============================================
// 1. std::mutex - 基本互斥鎖
// ============================================
void basic_mutex_example() {std::mutex mtx;int counter = 0;// 1.1 使用 lock_guard - 最簡單的RAII方式{std::lock_guard<std::mutex> lock(mtx);counter++;// 作用域結束時自動解鎖}// 1.2 手動加鎖解鎖(不推薦,容易忘記解鎖)mtx.lock();counter++;mtx.unlock();// 1.3 嘗試加鎖if (mtx.try_lock()) {counter++;mtx.unlock();}
}// ============================================
// 2. std::unique_lock - 靈活控制鎖
// ============================================
void unique_lock_example() {std::mutex mtx;// 2.1 基本使用(類似lock_guard){std::unique_lock<std::mutex> lock(mtx);// 臨界區代碼} // 自動解鎖// 2.2 延遲加鎖{std::unique_lock<std::mutex> lock(mtx, std::defer_lock);// 此時還沒有加鎖// 做一些不需要鎖的工作lock.lock();    // 手動加鎖// 臨界區工作lock.unlock();  // 手動解鎖// 更多不需要鎖的工作lock.lock();    // 再次加鎖// 更多臨界區工作} // 如果持有鎖,會自動解鎖// 2.3 嘗試加鎖{std::unique_lock<std::mutex> lock(mtx, std::try_to_lock);if (lock.owns_lock()) {// 成功獲取鎖std::cout << "獲取鎖成功\n";} else {std::cout << "獲取鎖失敗\n";}}// 2.4 超時加鎖(需要timed_mutex)std::timed_mutex timed_mtx;{std::unique_lock<std::timed_mutex> lock(timed_mtx, std::defer_lock);if (lock.try_lock_for(std::chrono::milliseconds(100))) {std::cout << "在100ms內獲取鎖成功\n";} else {std::cout << "超時,獲取鎖失敗\n";}}// 2.5 移動語義auto create_lock = []() {std::unique_lock<std::mutex> lock(mtx);return lock;  // 可以移動返回};std::unique_lock<std::mutex> moved_lock = create_lock();// moved_lock現在持有鎖
}// ============================================
// 3. std::shared_mutex - 讀寫鎖
// ============================================
void shared_mutex_example() {std::shared_mutex rw_mtx;std::string shared_data = "初始數據";// 3.1 讀鎖 - 多個線程可以同時讀auto reader = [&]() {std::shared_lock<std::shared_mutex> read_lock(rw_mtx);std::cout << "讀取: " << shared_data << std::endl;// 可以有多個線程同時執行這里};// 3.2 寫鎖 - 獨占訪問auto writer = [&]() {std::unique_lock<std::shared_mutex> write_lock(rw_mtx);shared_data = "更新后的數據";std::cout << "寫入完成" << std::endl;// 只有一個線程可以執行這里,且會阻塞所有讀者};// 啟動多個讀線程和一個寫線程std::vector<std::thread> threads;for (int i = 0; i < 3; ++i) {threads.emplace_back(reader);}threads.emplace_back(writer);for (auto& t : threads) {t.join();}
}// ============================================
// 4. std::recursive_mutex - 遞歸互斥鎖
// ============================================
void recursive_mutex_example() {std::recursive_mutex rec_mtx;int count = 0;std::function<void(int)> recursive_func = [&](int n) {std::lock_guard<std::recursive_mutex> lock(rec_mtx);count++;std::cout << "遞歸層級: " << n << ", count: " << count << std::endl;if (n > 0) {recursive_func(n - 1);  // 同一線程可以多次獲取鎖}};recursive_func(3);
}// ============================================
// 5. std::timed_mutex - 超時互斥鎖
// ============================================
void timed_mutex_example() {std::timed_mutex timed_mtx;// 5.1 嘗試在指定時間內獲取鎖if (timed_mtx.try_lock_for(std::chrono::milliseconds(100))) {std::cout << "在100ms內獲取鎖成功\n";// 臨界區工作timed_mtx.unlock();} else {std::cout << "超時,獲取鎖失敗\n";}// 5.2 嘗試在指定時間點前獲取鎖auto timeout_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(200);if (timed_mtx.try_lock_until(timeout_time)) {std::cout << "在指定時間點前獲取鎖成功\n";timed_mtx.unlock();} else {std::cout << "超時,獲取鎖失敗\n";}
}// ============================================
// 6. 多鎖管理 - 避免死鎖
// ============================================
void multi_lock_example() {std::mutex mtx1, mtx2;// 6.1 std::lock - 同時鎖定多個互斥鎖,避免死鎖{std::lock(mtx1, mtx2);  // 原子性地鎖定兩個互斥鎖std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);// 臨界區代碼}// 6.2 std::scoped_lock (C++17) - 更簡單的多鎖管理{std::scoped_lock lock(mtx1, mtx2);  // 自動管理多個鎖// 臨界區代碼}
}// ============================================
// 7. 條件變量配合使用
// ============================================
void condition_variable_example() {std::mutex mtx;std::condition_variable cv;bool ready = false;// 等待線程auto waiter = [&]() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [&] { return ready; });  // 等待條件滿足std::cout << "條件滿足,繼續執行\n";};// 通知線程auto notifier = [&]() {std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one();  // 通知等待的線程};std::thread t1(waiter);std::thread t2(notifier);t1.join();t2.join();
}// ============================================
// 8. 實際應用示例 - 線程安全的計數器
// ============================================
class ThreadSafeCounter {
private:mutable std::mutex mtx_;int count_ = 0;public:void increment() {std::lock_guard<std::mutex> lock(mtx_);++count_;}void decrement() {std::lock_guard<std::mutex> lock(mtx_);--count_;}int get() const {std::lock_guard<std::mutex> lock(mtx_);return count_;}// 復雜操作示例void add_if_positive(int value) {std::unique_lock<std::mutex> lock(mtx_);if (count_ > 0) {count_ += value;}}
};// ============================================
// 9. 性能考慮和最佳實踐
// ============================================
void performance_tips() {std::mutex mtx;// ? 好的做法:盡量縮小臨界區{int temp_result = 0;// 在鎖外做復雜計算for (int i = 0; i < 1000; ++i) {temp_result += i * i;}std::lock_guard<std::mutex> lock(mtx);// 只在必要時持有鎖// shared_data = temp_result;}// ? 不好的做法:在臨界區內做復雜計算{std::lock_guard<std::mutex> lock(mtx);// 不要在鎖內做復雜計算int result = 0;for (int i = 0; i < 1000; ++i) {result += i * i;}// shared_data = result;}
}int main() {std::cout << "=== C++ 互斥鎖使用示例 ===" << std::endl;basic_mutex_example();unique_lock_example();shared_mutex_example();recursive_mutex_example();timed_mutex_example();multi_lock_example();condition_variable_example();// 測試線程安全計數器ThreadSafeCounter counter;std::vector<std::thread> threads;for (int i = 0; i < 10; ++i) {threads.emplace_back([&counter]() {for (int j = 0; j < 100; ++j) {counter.increment();}});}for (auto& t : threads) {t.join();}std::cout << "最終計數: " << counter.get() << std::endl;return 0;
}

核心概念總結
1. 互斥鎖類型

  • std::mutex: 基本互斥鎖,最常用
  • std::recursive_mutex: 遞歸鎖,同一線程可多次獲取
  • std::timed_mutex: 支持超時的互斥鎖
  • std::shared_mutex: 讀寫鎖,支持多讀者單寫者

2. 鎖管理器

  • std::lock_guard: 最簡單的RAII鎖,構造時加鎖,析構時解鎖
  • std::unique_lock: 靈活的鎖管理器,支持延遲加鎖、手動控制等
  • std::shared_lock: 用于共享鎖(讀鎖)
  • std::scoped_lock: C++17引入,用于管理多個鎖

3. 鎖標簽

  • std::defer_lock: 延遲加鎖
  • std::try_to_lock: 嘗試加鎖
  • std::adopt_lock: 接管已經持有的鎖

4. 最佳實踐

  1. 優先使用 lock_guard - 簡單場景的首選
  2. 需要靈活控制時使用 unique_lock - 如需要手動解鎖/加鎖
  3. 讀多寫少用 shared_mutex - 提高并發性能
  4. 盡量縮小臨界區 - 減少鎖持有時間
  5. 避免死鎖 - 使用 std::lock 或 std::scoped_lock 管理多個鎖
  6. 配合條件變量使用 unique_lock - 因為條件變量需要能夠釋放鎖

5. 選擇建議

  • 簡單保護:std::mutex + std::lock_guard
  • 需要靈活控制:std::mutex + std::unique_lock
  • 讀多寫少:std::shared_mutex + std::shared_lock/std::unique_lock
  • 遞歸調用:std::recursive_mutex
  • 超時需求:std::timed_mutex

這些工具組合使用可以解決絕大多數多線程同步問題。

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

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

相關文章

Android Handler機制與底層原理詳解

Android 的 Handler 機制是跨線程通信和異步消息處理的核心框架&#xff0c;它構成了 Android 應用響應性和事件驅動模型的基礎&#xff08;如 UI 更新、后臺任務協調&#xff09;。其核心思想是 “消息隊列 循環處理”。 核心組件及其關系Handler (處理器): 角色: 消息的發送…

jQuery JSONP:實現跨域數據交互的利器

jQuery JSONP&#xff1a;實現跨域數據交互的利器 引言 隨著互聯網的發展&#xff0c;跨域數據交互的需求日益增加。在Web開發中&#xff0c;由于同源策略的限制&#xff0c;直接通過XMLHttpRequest請求跨域數據會遇到諸多問題。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 實現分布式鎖的優勢和劣勢

在分布式系統中&#xff0c;實現分布式鎖是確保多個節點間互斥訪問共享資源的一種常見需求。Redis 集群 和 zookeeper 都可以用來實現這一功能&#xff0c;但它們有著各自不同的優勢和劣勢。 CAP 理論&#xff1a; 在設計一個分布式系統時&#xff0c;一致性&#xff08;Consis…

如何備份vivo手機中的聯系人?

隨著vivo移動設備在全球設立7個研發中心&#xff0c;vivo正在進入更多的國家。如今&#xff0c;越來越多的人開始使用vivo手機。以vivo X100為例&#xff0c;它配備了主攝像頭和多個輔助攝像頭&#xff0c;提供多樣化的拍攝選項&#xff0c;并搭載了最新的FunTouch OS&#xff…

python腳本編程:使用BeautifulSoup爬蟲庫獲取熱門單機游戲排行榜

BeautifulSoup是一個便捷的解析html頁面元素的python庫&#xff0c;此處用來寫一個簡單的爬蟲批量抓取國內游戲資訊網站的近期熱門單機游戲排行榜。 網頁來源如下所示代碼 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面詳解:從傳統方式到現代配置系統

C#配置全面詳解&#xff1a;從傳統方式到現代配置系統 在軟件開發中&#xff0c;配置是指應用程序運行時可調整的參數集合&#xff0c;如數據庫連接字符串、API 地址、日志級別等。將這些參數從代碼中分離出來&#xff0c;便于在不修改代碼的情況下調整應用行為。C# 提供了多種…

數據中臺架構解析:湖倉一體的實戰設計

目錄 一、數據中臺與湖倉一體架構是什么 1. 數據中臺 2. 湖倉一體架構 3. 湖倉一體在數據中臺里的價值 二、湖倉一體架構的核心部件 1. 數據湖 2. 數據倉庫 3. 數據集成工具 4. 數據分析與處理引擎 三、湖倉一體架構實戰設計 1. 需求分析與規劃 2. 數據湖建設 3. …

SQL Server表分區技術詳解

表分區概述 表分區是將大型數據庫表物理分割為多個較小單元的技術,邏輯上仍表現為單一實體。該技術通過水平分割數據顯著提升查詢性能,尤其針對TB級數據表可降低90%的響應時間。典型應用場景包含訂單歷史表、日志記錄表等具有明顯時間特征的業務數據,以及需要定期歸檔的審計…

WHIP(WebRTC HTTP Ingestion Protocol)詳解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;詳解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一種基于 HTTP 的協議&#xff0c;用于將 WebRTC 媒體流推送到媒體服務器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是為簡化 WebRT…

圖像噪點消除:用 OpenCV 實現多種濾波方法

在圖像處理中&#xff0c;噪點是一個常見的問題。它可能是由于圖像采集設備的缺陷、傳輸過程中的干擾&#xff0c;或者是光照條件不佳引起的。噪點會影響圖像的質量和后續處理的效果&#xff0c;因此消除噪點是圖像預處理的重要步驟之一。本文將介紹如何使用 OpenCV 實現幾種常…

AI的Prompt提示詞:英文寫好還是中文好?

在與AI人大模型交互時,Prompt(提示詞)的質量直接決定了輸出的精準度和有效性。一個常見的問題是:究竟是用英文寫Prompt好,還是用中文寫更好?這并非一個簡單的二元選擇,而是涉及到語言模型的底層邏輯、表達的精確性以及個人使用習慣的綜合考量。 英文Prompt的優勢 模型訓…

react的條件渲染【簡約風5min】

const flag1true; console.log(flag1&&hello); console.log(flag1||hello); const flag20; console.log(flag2&&hello); console.log(flag2||hello); // &&運算符&#xff0c;如果第一個條件為假&#xff0c;則返回第一個條件&#xff0c;否則返回第二…

【RK3568+PG2L50H開發板實驗例程】FPGA部分 | 紫光同創 IP core 的使用及添加

本原創文章由深圳市小眼睛科技有限公司創作&#xff0c;版權歸本公司所有&#xff0c;如需轉載&#xff0c;需授權并注明出處&#xff08;www.meyesemi.com)1.實驗簡介實驗目的&#xff1a;了解 PDS 軟件如何安裝 IP、使用 IP 以及查看 IP 手冊實驗環境&#xff1a;Window11 PD…

thinkphp微信小程序一鍵獲取手機號登陸(解密數據)

微信小程序獲取手機號登錄的步驟相對較為簡單,主要分為幾個部分: 1.用戶授權獲取手機號: 微信小程序通過調用 wx.getPhoneNumber API 獲取用戶授權后,獲取手機號。 2.前端獲取用戶的手機號: 用戶在小程序中點擊獲取手機號時,系統會彈出授權框,用戶同意后,你可以通過 …

數據庫設計精要:完整性和范式理論

文章目錄數據的完整性實體的完整性主鍵域完整性參照完整性外鍵多表設計/多表理論一對一和一對多多對多數據庫的設計范式第一范式&#xff1a;原子性第二范式&#xff1a;唯一性第三范式&#xff1a;不冗余性數據的完整性 實體的完整性 加主鍵&#xff0c;保證一個表中每一條數…

智能推薦社交分享小程序(websocket即時通訊、協同過濾算法、時間衰減因子模型、熱度得分算法)

&#x1f388;系統亮點&#xff1a;websocket即時通訊、協同過濾算法、時間衰減因子模型、熱度得分算法&#xff1b;一.系統開發工具與環境搭建1.系統設計開發工具后端使用Java編程語言的Spring boot框架項目架構&#xff1a;B/S架構運行環境&#xff1a;win10/win11、jdk17小程…

部署NextCloud AIO + Frp + nginx-proxy-manager內網穿透私有云服務

網絡拓撲 假設已有域名為nextcloud.yourhost.com 用戶通過域名https訪問 -> Nginx -> frps -> frpc -> NextCloud 其中Nginx和frps安裝在具有公網IP的服務器上&#xff0c;frpc和NextCloud安裝在內網服務器中。 Nginx配置 通過docker安裝nginx-proxy-manager 外…

【源力覺醒 創作者計劃】文心開源大模型ERNIE-4.5-0.3B-Paddle私有化部署保姆級教程及技術架構探索

一起來輕松玩轉文心大模型吧&#x1f449;一文心大模型免費下載地址: https://ai.gitcode.com/theme/1939325484087291906 前言 2025年6月30日&#xff0c;百度正式開源文心大模型4.5系列&#xff08;ERNIE 4.5&#xff09;&#xff0c;涵蓋10款不同參數規模的模型&#xff0…

大模型面試:如何解決幻覺問題

在大模型面試中回答“如何解決幻覺”問題時&#xff0c;需要展現你對問題本質的理解、技術方案的掌握以及工程實踐的洞察。以下是一個結構化的回答框架和關鍵點&#xff0c;供你參考&#xff1a;回答框架&#xff1a;問題理解 -> 解決方案 -> 總結 1. 明確問題&#xff0…

matlab實現五自由度機械臂阻抗控制下的力跟蹤

五自由度機械臂阻抗控制下的力跟蹤,可以實現對力的跟蹤反饋&#xff0c;基于MATLAB的機器人工具箱 eyebot.m , 767 zuakang_wailiraodong.m , 2568 colormp.mat , 682