std::mutex
C++11中新增了<mutex>,它是C++標準程序庫中的一個頭文件,定義了C++11標準中的一些互斥訪問的類與方法等。
C++11標準庫定義了4個互斥類:
std::mutex
std::mutex 是C++11 中最基本的互斥量,std::mutex 對象提供了獨占所有權的特性——即不支持遞歸地對 std::mutex 對象上鎖,而 std::recursive_lock 則可以遞歸地對互斥量對象上鎖。
-
下面給出一個與 std::mutex 的小例子(http://www.cplusplus.com/reference/mutex/mutex/try_lock/):
std::recursive_mutex
官方文檔是這么說的:
recursive_mutex 類是同步原語,能用于保護共享數據免受個多線程同時訪問。
recursive_mutex 提供排他性遞歸所有權語義:
-
調用方線程在從它成功調用 lock 或 try_lock 開始的時期里占有 recursive_mutex 。此時期間,線程可以進行對 lock 或 try_lock 的附加調用。所有權的時期在線程調用 unlock 匹配次數時結束。
-
線程占有 recursive_mutex 時,若其他所有線程試圖要求 recursive_mutex 的所有權,則它們將阻塞(對于調用 lock )或收到 false 返回值(對于調用 try_lock )。
-
可鎖定 recursive_mutex 次數的最大值是未指定的,但抵達該數后,對 lock 的調用將拋出 std::system_error 而對 try_lock 的調用將返回 false 。
若 recursive_mutex 在仍為某線程占有時被銷毀,則程序行為未定義。recursive_mutex 類滿足互斥體 (Mutex) 和標準布局類型 (StandardLayoutType) 的所有要求。
用人話說就是:遞歸互斥鎖可以被同一個線程多次加鎖,以獲得對互斥鎖對象的多層所有權。例如,同一個線程多個函數訪問臨界區時都可以各自加鎖,執行后各自解鎖。std::recursive_mutex釋放互斥量時需要調用與該鎖層次深度相同次數的unlock(),即lock()次數和unlock()次數相同。可見,線程申請遞歸互斥鎖時,如果該遞歸互斥鎖已經被當前調用線程鎖住,則不會產生死鎖。
recursive_mutex 的使用場景之一是保護類中的共享狀態,而類的成員函數可能相互調用。官方的小例子:
#include <iostream> #include <thread> #include <mutex>class X {std::recursive_mutex m;std::string shared;public:void fun1() {std::lock_guard<std::recursive_mutex> lk(m);shared = "fun1";std::cout << "in fun1, shared variable is now " << shared << '\n';}void fun2() {std::lock_guard<std::recursive_mutex> lk(m);shared = "fun2";std::cout << "in fun2, shared variable is now " << shared << '\n';fun1(); // 遞歸鎖在此處變得有用std::cout << "back in fun2, shared variable is " << shared << '\n';}; };int main() {X x;std::thread t1(&X::fun1, &x);std::thread t2(&X::fun2, &x);t1.join();t2.join(); }可以看出fun2調用的fun1,他們都對recursive_mutex m?加鎖,如果不是recursive的,那么這里會產生死鎖。假設fun2拿到了鎖,然后調用fun1又要去拿鎖,又不是recursive的,那么就會hang在fun1里邊。
?
std::time_mutex
官方文檔是這么說的:
recursive_timed_mutex 是同步原語,能用于保護共享數據免受從多個線程同時訪問。
以類似 std::recursive_mutex 的方式, recursive_timed_mutex 提供排他性遞歸所有權語義。另外, recursive_timed_mutex 通過 try_lock_for 與 try_lock_until 方法,提供帶時限地試圖要求 recursive_timed_mutex 所有權的能力。
recursive_timed_mutex 類滿足定時互斥體 (TimedMutex) 和標準布局類型 (StandardLayoutType) 的所有要求。
?
換成人話說:
std::time_mutex 比 std::mutex 多了兩個成員函數,try_lock_for(),try_lock_until()。
try_lock_for 函數接受一個時間范圍,表示在這一段時間范圍之內線程如果沒有獲得鎖則被阻塞住(與 std::mutex 的 try_lock() 不同,try_lock 如果被調用時沒有獲得鎖則直接返回 false),如果在此期間其他線程釋放了鎖,則該線程可以獲得對互斥量的鎖,如果超時(即在指定時間內還是沒有獲得鎖),則返回 false。
try_lock_until 函數則接受一個時間點作為參數,在指定時間點未到來之前線程如果沒有獲得鎖則被阻塞住,如果在此期間其他線程釋放了鎖,則該線程可以獲得對互斥量的鎖,如果超時(即在指定時間內還是沒有獲得鎖),則返回 false。
舉個try_lock_for的小例子:
#include <iostream> #include <mutex> #include <thread> #include <vector> #include <sstream>std::mutex cout_mutex; // 控制到 std::cout 的訪問 std::timed_mutex mutex;void job(int id) {using Ms = std::chrono::milliseconds;std::ostringstream stream;for (int i = 0; i < 3; ++i) {if (mutex.try_lock_for(Ms(100))) {stream << "success ";std::this_thread::sleep_for(Ms(100));mutex.unlock();} else {stream << "failed ";}std::this_thread::sleep_for(Ms(100));}std::lock_guard<std::mutex> lock(cout_mutex);std::cout << "[" << id << "] " << stream.str() << "\n"; }int main() {std::vector<std::thread> threads;for (int i = 0; i < 4; ++i) {threads.emplace_back(job, i);}for (auto& i: threads) {i.join();} }可能的輸出:
[0] failed failed failed [3] failed failed success [2] failed success failed [1] success failed successstd::recursive_timed_mutex
這個就好說的,就是疊加recursive 和time兩大神功的mutex。
總結
以上是生活随笔為你收集整理的std::mutex的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lambda 和 std::functi
- 下一篇: std::future和std::pro