C++多线程:互斥变量 std::mutex
文章目錄
- 描述
- 成員函數
- 總結
描述
- 頭文件
<mutex> - 使用
std::mutex <variable> - 簡介
mutex是一種多線程變成中的同步原語,它能夠讓共享數據不被多個線程同時訪問,它不支持遞歸得對互斥對象上鎖 - 特點
- 用方線程從它成功調用 lock 或 try_lock 開始,到它調用 unlock 為止占有 mutex
- 線程占有 mutex 時,所有其他線程若試圖要求 mutex 的所有權,則將阻塞(對于 lock 的調用)或收到 false 返回值(對于 try_lock )
- 調用方線程在調用 lock 或 try_lock 前必須不占有 mutex ,否則無法獲取<mutex>變量
成員函數
-
構造函數
std::mutex::mutexconstexpr mutex() noexcept;(1) mutex( const mutex& ) = delete;(2)(1)構造mutex實例,
mutex實例構造完成之后是處于unlocked狀態
(2)mutex的拷貝構造函數是不存在的 -
std::mutex::~mutex析構函數
銷毀互斥變量
若互斥為任何線程占有,或若任何線程在保有任何互斥的所有權時終止,則行為未定義 -
賦值運算符,不存在
-
std::mutex::lock
鎖定互斥。若另一線程已鎖定互斥,則到 lock 的調用將阻塞執行,直至獲得鎖
錯誤發生時拋出 std::system_error ,包括底層操作系統阻止 lock 滿足其規定的錯誤。在拋出任何異常的情況下,不鎖定互斥。所以,直接使用mutex的lock成員是無處法處理異常的情況。#include <iostream> #include <chrono> #include <thread> #include <mutex>int g_num = 0; // protected by g_num_mutex 共享數據 std::mutex g_num_mutex;void slow_increment(int id) {for (int i = 0; i < 3; ++i) {g_num_mutex.lock();++g_num;std::cout << id << " => " << g_num << '\n';g_num_mutex.unlock();//chrono是C++的時間庫,提供1s線程的休眠std::this_thread::sleep_for(std::chrono::seconds(1));} }int main() {//0號線程和1號線程交叉執行對全局變量g_num對累加操作,執行完成之后sleep 1秒std::thread t1(slow_increment, 0);std::thread t2(slow_increment, 1);t1.join();t2.join(); }輸出如下
0 => 1 1 => 2 0 => 3 1 => 4 0 => 5 1 => 6 -
std::mutex::try_lock
嘗試鎖定互斥。立即返回。成功獲得鎖時返回 true ,否則返回 false。
若此操作返回 true ,則同一互斥上的先前 unlock() 操作同步于(定義于 std::memory_order )它。注意若此操作返回 false ,則先前的 lock() 不與之同步#include <chrono> #include <mutex> #include <thread> #include <iostream> // std::coutstd::chrono::milliseconds interval(100);std::mutex mutex; int job_shared = 0; // 兩個線程都能修改 'job_shared',// mutex 將保護此變量int job_exclusive = 0; // 只有一個線程能修改 'job_exclusive'// 不需要保護// 此線程能修改 'job_shared' 和 'job_exclusive' void job_1() {std::this_thread::sleep_for(interval); // 令 'job_2' 持鎖while (true) {// 嘗試鎖定 mutex 以修改 'job_shared'if (mutex.try_lock()) {std::cout << "job shared (" << job_shared << ")\n";mutex.unlock();return;} else {// 不能獲取鎖以修改 'job_shared'// 但有其他工作可做++job_exclusive;std::cout << "job exclusive (" << job_exclusive << ")\n";std::this_thread::sleep_for(interval);}} }// 此線程只能修改 'job_shared' void job_2() {mutex.lock();std::this_thread::sleep_for(5 * interval);++job_shared;mutex.unlock(); }int main() {/*可以看到job1中的實現,使用的是try_lock獲取鎖,因為剛開始job1線程會進行100毫秒的休眠,所以cpu會先去執行job2,但是job2使用的是lock成員所以在job2中sleep 500毫秒的過程中執行job1時try_lock返回false,則執行exclusive輸出.當job2獲取不到鎖,job1休眠結束之后釋放鎖,則job1重新獲取鎖成功*/std::thread thread_1(job_1);std::thread thread_2(job_2);thread_1.join();thread_2.join(); }輸出如下
job exclusive (1) job exclusive (2) job exclusive (3) job exclusive (4) job shared (1) -
std::mutex::unlock解鎖mutex實例
使用前提是當前線程必須被mutex的實例鎖定,否則改函數的調用是未定義的
注意,當前成員與lock()成員,一般不直接調用,因為對異常情況的處理并不友好(程序鎖定期間發生異常,進程就直接退出),所以一般與std::unique_lock 與 std::lock_guard 管理排他性鎖 一起使用
具體使用實例可以參考如上兩個代碼。
總結
mutex互斥變量,并提供來了獨占鎖特性。為C++提供了多線程訪問共享數據的保護措施,同時引入了像unique_lock和lock_gurad異常處理鎖機制來規避mutex的成員處理異常情況的不足。
總結
以上是生活随笔為你收集整理的C++多线程:互斥变量 std::mutex的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字幕左下角这个怎么弄
- 下一篇: 英雄联盟装备影焰介绍