《C++ 108好庫》之2 多線程庫thread,mutex,condition_variable,this_thread

《C++ 108好庫》之之2 多線程庫thread,mutex,condition_variable,this_thread

  • 《C++ 108好庫》之2 多線程庫thread,mutex,condition_variable,this_thread
  • std::thread類
  • ??互斥量(Mutex)??類
    • std::mutex??類
    • std::lock_guard類
    • std::unique_lock類
  • ??條件變量(Condition Variable)??類
  • 獲取線程ID和 延時
  • 使用例子
    • 創建線程
    • 使用mutex和Condition Variable的生產者-消費者模型

《C++ 108好庫》之2 多線程庫thread,mutex,condition_variable,this_thread

C++11 中,多線程編程通過標準庫 正式引入,提供了跨平臺的線程管理能力。
多線程一般由這些類合作構成:std::thread類、std::mutex??類、std::lock_guard類、 std::unique_lock類、condition_variable類

std::thread類

1 ??創建線程??
explicit thread(_Callable&& __f, _Args&&… __args)
使用 std::thread類創建線程,構造函數接受函數對象及參數:
向線程函數傳遞參數時,參數會被復制到線程的獨立內存中;如果希望傳遞引用,需要使用std::ref。

2??線程管理??:
join():等待線程完成。
detach():將線程與主線程分離,使其獨立運行。一旦分離,就不能再與之通信。
注意:在銷毀std::thread對象之前,必須調用join()或detach(),否則程序會終止(調用std::terminate)。

??互斥量(Mutex)??類

C++11提供了std::mutex用于保護共享數據,防止數據競爭。

std::mutex??類

std::mutex()

std::mutex::lock() :調用此函數會嘗試??鎖定??互斥體。
行為:??如果互斥體當前??未被任何線程鎖定??,則調用線程獲得鎖,函數立即返回。如果互斥體??已被其他線程鎖定??,則調用線程會被??阻塞??(掛起),直到持有鎖的線程解鎖該互斥體。一旦解鎖,等待的線程之一(取決于調度)會獲得鎖并繼續執行。
??特點:?? 阻塞調用。如果忘記解鎖會導致死鎖。
??用法:?? 當你需要確保臨界區被獨占訪問,并且可以接受線程阻塞等待時使用。

std::mutex::try_lock(): 調用此函數會??嘗試??鎖定互斥體,但??不會阻塞??調用線程。
??行為:??如果互斥體當前??未被鎖定??,則調用線程獲得鎖,函數返回 true。如果互斥體??已被鎖定??(無論是當前線程還是其他線程),則函數??立即返回 false??,線程繼續執行而不會被阻塞。
??特點:?? 非阻塞調用。需要檢查返回值來判斷是否成功獲得鎖。
??用法:?? 當你需要在鎖不可用時做其他事情,避免阻塞線程時使用。常用于輪詢、避免死鎖策略(如按固定順序獲取多個鎖失敗時釋放已持有的鎖)或非關鍵路徑的優化。

std::mutex::unlock():解鎖

std::lock_guard類

它在構造時自動鎖定給定的互斥體,并在析構時(通常是離開作用域時)自動解鎖它。
??構造時:?? 調用傳入的互斥體(如 std::mutex)的 lock()方法。這會阻塞直到獲得鎖。
??析構時:?? 調用互斥體的 unlock()方法。
用法:std::lock_guardstd::mutex lock(mtx); // 構造時自動調用 mtx.lock()

std::unique_lock類

功能比 lock_guard??更強大、更靈活??。它也管理互斥體的鎖定和解鎖,但提供了更多的控制選項。
??行為/特點:??
??靈活的構造:??默認構造:創建一個不關聯任何互斥體的 unique_lock。
關聯互斥體并立即鎖定(阻塞):unique_lock lock(mtx);(等價于 lock_guard)
關聯互斥體但??延遲鎖定??:unique_lock lock(mtx, std::defer_lock);構造時不鎖定,稍后手動調用 lock(), try_lock()或 try_lock_for()/try_lock_until()(針對 std::timed_mutex)。
關聯互斥體并嘗試鎖定:unique_lock lock(mtx, std::try_to_lock);構造時調用 mtx.try_lock()。
關聯互斥體并假設已鎖定(接管所有權):unique_lock lock(mtx, std::adopt_lock);假設調用線程已經持有 mtx的鎖,unique_lock負責后續解鎖。
手動控制:??
lock(): 阻塞鎖定關聯的互斥體(如果尚未鎖定)。
try_lock(): 嘗試非阻塞鎖定關聯的互斥體。
unlock(): ??手動解鎖??關聯的互斥體,在 unique_lock析構前可以臨時釋放鎖(這在 lock_guard中是不可能的)。析構時如果互斥體仍被該 unique_lock持有,會自動解鎖。
release(): 釋放對互斥體的所有權管理(返回互斥體指針),不再負責解鎖。調用者需手動管理。
??所有權:??
可移動 (std::move),但不可復制。鎖的所有權可以在 unique_lock對象之間轉移。
??條件變量:?? std::condition_variable::wait等函數??必須??使用 std::unique_lockstd::mutex作為參數,因為它需要能在等待時解鎖和重新鎖定互斥體(這是 lock_guard做不到的)。

??條件變量(Condition Variable)??類

<condition_variable>
用于線程間的同步,允許線程在某些條件不滿足時休眠,直到被其他線程通知。通常與互斥量一起使用。
void notify_one() noexcept;
void notify_all() noexcept;
wait(unique_lock& __lock) noexcept;
wait_until(unique_lock& __lock,const chrono::time_point<__clock_t, _Duration>& __atime)
wait_for(unique_lock& __lock, const chrono::duration<_Rep, _Period>& __rtime)

獲取線程ID和 延時

std::this_thread里的函數
inline thread::id get_id()
獲取??當前執行線程的唯一標識符??。
std::thread::id main_id = std::this_thread::get_id(); // 輸出示例:0x70000a15c000

inline void sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
使??當前線程阻塞??一段指定的??相對時間??。
std::this_thread::sleep_for(std::chrono::seconds(1));

inline void sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
使??當前線程阻塞??直到??絕對時間點??。

使用例子

創建線程

std::thread thread_hello(hello,"LiHua");
thread_hello.join();

傳入函數給線程
void hello(const std::string str) {
std::cout << "hello world! "<<str<<std::endl;
}

使用mutex和Condition Variable的生產者-消費者模型

std::thread thread_producer(producer);
thread_producer.detach();std::thread thread_consumer(consumer);
thread_consumer.join();

其中的線程函數

std::queue<int> dataQueue;
std::mutex mtx_test_thread;
std::condition_variable cv_test_thread;
void producer() {for (int i = 0; i < 50; ++i) {{std::lock_guard<std::mutex> lock(mtx_test_thread);dataQueue.push(i); std::cout << "push:" << i << std::endl;}std::this_thread::sleep_for(std::chrono::seconds(1));cv_test_thread.notify_one(); // 通知消費者}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx_test_thread);cv_test_thread.wait(lock, [] { return !dataQueue.empty(); });int value = dataQueue.front();dataQueue.pop();lock.unlock();if (value == -1) break; // 終止條件std::cout << "Consumed: " << value << std::endl;}
}

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

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

相關文章

Android系統框架知識系列(二十):專題延伸:JVM vs ART/Dalvik - Android運行時演進深度解析

?關鍵詞?&#xff1a;運行時優化、AOT編譯、JIT編譯、內存管理、電池效率、性能分析一、Android運行時演進背景1. 移動環境的特殊挑戰Android運行時環境的演進源于移動設備的獨特限制&#xff1a;?移動設備約束條件?&#xff1a;?有限的內存資源?&#xff1a;早期設備僅1…

ubuntu 22 安裝輕量級桌面Xfce并使用xrdp遠程桌面連接

1.安裝Xfce:sudo apt install xubuntu-desktop -y2.安裝xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 遠程連接端口&#xff0c;默認是3389&#xff0c;可以改成自己喜歡的端口... ; ; Session types ;; Some sess…

【Flask】測試平臺開發,數據看板開發-第二十一篇

概述&#xff1a;在前面我們已經實現了我們的產品創建管理&#xff0c;應用管理管理&#xff0c;需求提測管理但是每周提測了多少需求&#xff0c;創建了哪些產品&#xff0c;我們是不是看著不是很直觀&#xff0c;接下來我們就需要開發一個數據看板功能&#xff0c;實現能夠看…

我是程序員,不是程序猿:請別把我當猴耍——拒絕被低估,用專業贏得尊重

摘要 本文旨在深度剖析“程序員”與“程序猿”一字之差背后所反映的職業尊嚴與身份認同問題。我們生活在一個技術驅動的時代&#xff0c;但對技術創造者的認知卻常常被“程序猿”、“碼農”等標簽簡單化、甚至矮化。本文將從正名開始&#xff0c;辨析“程序員”的專業內涵&…

C++中vector刪除操作的安全隱患與最佳實踐

std::vector 是C標準模板庫&#xff08;STL&#xff09;中最常用的動態數組容器&#xff0c;提供了高效的隨機訪問和動態擴容能力。然而&#xff0c;其刪除操作如果使用不當&#xff0c;會引入嚴重的安全隱患&#xff0c;包括未定義行為、內存泄漏和數據競爭等問題。本文將深入…

Unix/Linux 系統中的 `writev` 系統調用

<摘要> 本文對 Unix/Linux 系統中的 writev 系統調用進行了全面深入的解析。內容涵蓋了其產生的背景&#xff08;從傳統 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系統調用流程&#xff09;。重點剖析了其設計意圖&…

深入理解 Android targetSdkVersion:從 Google Play 政策到依賴沖突

深入理解 Android targetSdkVersion&#xff1a;從 Google Play 政策到依賴沖突 作為 Android 開發者&#xff0c;你很可能在 Android Studio 中見過這條提示&#xff1a;Google Play requires that apps target API level 33 or higher。它像一個盡職的提醒者&#xff0c;時常…

灰匣(GrayBox)1.0.0 發布【提升系統權限APP】

灰匣是一個提升系統權限的工具&#xff0c;可以配合Root、三方軟件&#xff08;Shizuku&#xff09;以及【設備管理員】&#xff08;設備所有者&#xff09;實現一些高級功能及底層接口&#xff0c;可以自動隔離&#xff08;凍結/禁用&#xff09;不必要的應用&#xff0c;如某…

PAT 1104 Sum of Number Segments

這一題的大意就是找一個數組中的所有子數組&#xff0c;它們的累加和為多少&#xff0c; 題目上給出的數據范圍是O(n^5)那么只能遍歷一次&#xff0c;不能用暴力的方法求出。 看到這一題我有兩個思路&#xff1a; 1.試圖用雙指針和滑動窗口來把O&#xff08;n^2)的時間復雜度降…

[萬字長文]AJAX入門-常用請求方法和數據提交、HTTP協議-報文、接口文檔、案例實戰

本系列可作為前端學習系列的筆記&#xff0c;代碼的運行環境是在VS code中&#xff0c;小編會將代碼復制下來&#xff0c;大家復制下來就可以練習了&#xff0c;方便大家學習。 HTML、CSS、JavaScript系列文章 已經收錄在前端專欄&#xff0c;有需要的寶寶們可以點擊前端專欄查…

Codesy中的UDP發送信息

Codesy UDP通訊 概述 CAA Net Base Services UDP通訊的建立 發送UDP 狀態控制 效果 概述 Codesys中默認安裝的通訊支持很多,不安裝其他的軟件也可以實現TCP通訊。但是,在使用UDP通訊時,因為我們的PLC有兩個網卡,一般我們把第一個網口做編程和HMI用,把的個網口做外部通訊,…

神經網絡之深入理解偏置

&#x1f50d; 1. 表達能力&#xff1a;無偏模型不能表示全體函數族 ? 有偏線性變換&#xff1a; yWxb&#xff08;仿射變換&#xff09; y Wx b \quad \text{&#xff08;仿射變換&#xff09;} yWxb&#xff08;仿射變換&#xff09; 能表示任意線性函數 平移是仿射空間的…

小白必看:AI智能體零基礎搭建全攻略!

寫在前面&#xff1a;別怕&#xff0c;真的不需要技術背景&#xff01; 你是不是經常聽到"AI智能體"、"大模型"這些高大上的詞&#xff0c;總覺得那是技術大牛的專利&#xff1f;別擔心&#xff0c;這篇教程就是為你準備的&#xff01;我們將用最通俗的語…

React state在setInterval里未獲取最新值的問題

目錄 一、問題描述 二、解決方案 方案一&#xff0c;使用函數式更新 方案二&#xff0c;使用 useRef 保存最新值 一、問題描述 在 React 中&#xff0c;當在 setInterval或setTimeout 中使用 setState 時&#xff0c;經常會遇到狀態不是最新值的問題。這是因為閉包導致的&a…

x86 架構 Docker 鏡像遷移至 ARM 環境的詳細指南

目錄 一、問題背景與分析 二、解決步驟 &#xff08;一&#xff09;檢查 docker-compose 版本 &#xff08;二&#xff09;升級 docker-compose 1. 對于 Linux 系統 2. 對于 Windows 系統 &#xff08;三&#xff09;驗證升級 &#xff08;四&#xff09;重新運行 dock…

零代碼部署工業數據平臺:TRAE + TDengine IDMP 實踐

對于編程初學者來說&#xff0c;軟件開發流程中的開發環境配置、安裝異常或報錯往往需要花費大量時間查閱資料和反復試錯&#xff0c;才能正常安裝和啟動某些軟件工具。現在&#xff0c;在 TRAE 的幫助下&#xff0c;即使完全沒有接觸過編程&#xff0c;也能通過自然語言直接表…

史上最全Flink面試題(完整版)

1、簡單介紹一下 FlinkFlink 是一個框架和分布式處理引擎&#xff0c;用于對無界和有界數據流進行有狀態計算。并且 Flink 提供了數據分布、容錯機制以及資源管理等核心功能。Flink提供了諸多高抽象層的API以便用戶編寫分布式任務&#xff1a;DataSet API&#xff0c; 對靜態數…

C# .NET中使用log4Net日志框架指南

C# .NET中使用log4Net日志框架指南 log4Net是Apache基金會開發的一款高效、靈活的日志記錄框架&#xff0c;廣泛應用于.NET生態系統中。它支持多種日志輸出目標&#xff08;如文件、數據庫、控制臺&#xff09;&#xff0c;并提供細粒度的日志級別控制&#xff0c;幫助開發者監…

每日算法刷題Day68:9.10:leetcode 最短路6道題,用時2h30min

一. 單源最短路&#xff1a;Dijkstra 算法 1.套路 1.Dijkstra 算法介紹 (1)定義 g[i][j] 表示節點 i 到節點 j 這條邊的邊權。如果沒有 i 到 j 的邊&#xff0c;則 g[i][j]∞。 (2)定義 dis[i] 表示起點 k 到節點 i 的最短路長度&#xff0c;一開始 dis[k]0&#xff0c;其余 …

Spring Boot + Apache Tika 從文件或文件流中提取文本內容

應用效果&#xff1a;1、安裝 Apache Tika 依賴pom.xml<!-- Apache Tika 從文件中提取結構化文本和元數據 --><dependency><groupId>org.apache.tika</groupId><artifactId>tika-core</artifactId><version>2.9.2</version>&l…