std::mutex
C++11中新增了<mutex>,它是C++標(biāo)準(zhǔn)程序庫中的一個頭文件,定義了C++11標(biāo)準(zhǔn)中的一些互斥訪問的類與方法等。
C++11標(biāo)準(zhǔn)庫定義了4個互斥類:
std::mutex
std::mutex 是C++11 中最基本的互斥量,std::mutex 對象提供了獨(dú)占所有權(quán)的特性——即不支持遞歸地對 std::mutex 對象上鎖,而 std::recursive_lock 則可以遞歸地對互斥量對象上鎖。
-
下面給出一個與 std::mutex 的小例子(http://www.cplusplus.com/reference/mutex/mutex/try_lock/):
std::recursive_mutex
官方文檔是這么說的:
recursive_mutex 類是同步原語,能用于保護(hù)共享數(shù)據(jù)免受個多線程同時訪問。
recursive_mutex 提供排他性遞歸所有權(quán)語義:
-
調(diào)用方線程在從它成功調(diào)用 lock 或 try_lock 開始的時期里占有 recursive_mutex 。此時期間,線程可以進(jìn)行對 lock 或 try_lock 的附加調(diào)用。所有權(quán)的時期在線程調(diào)用 unlock 匹配次數(shù)時結(jié)束。
-
線程占有 recursive_mutex 時,若其他所有線程試圖要求 recursive_mutex 的所有權(quán),則它們將阻塞(對于調(diào)用 lock )或收到 false 返回值(對于調(diào)用 try_lock )。
-
可鎖定 recursive_mutex 次數(shù)的最大值是未指定的,但抵達(dá)該數(shù)后,對 lock 的調(diào)用將拋出 std::system_error 而對 try_lock 的調(diào)用將返回 false 。
若 recursive_mutex 在仍為某線程占有時被銷毀,則程序行為未定義。recursive_mutex 類滿足互斥體 (Mutex) 和標(biāo)準(zhǔn)布局類型 (StandardLayoutType) 的所有要求。
用人話說就是:遞歸互斥鎖可以被同一個線程多次加鎖,以獲得對互斥鎖對象的多層所有權(quán)。例如,同一個線程多個函數(shù)訪問臨界區(qū)時都可以各自加鎖,執(zhí)行后各自解鎖。std::recursive_mutex釋放互斥量時需要調(diào)用與該鎖層次深度相同次數(shù)的unlock(),即lock()次數(shù)和unlock()次數(shù)相同。可見,線程申請遞歸互斥鎖時,如果該遞歸互斥鎖已經(jīng)被當(dāng)前調(diào)用線程鎖住,則不會產(chǎn)生死鎖。
recursive_mutex 的使用場景之一是保護(hù)類中的共享狀態(tài),而類的成員函數(shù)可能相互調(diào)用。官方的小例子:
#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調(diào)用的fun1,他們都對recursive_mutex m?加鎖,如果不是recursive的,那么這里會產(chǎn)生死鎖。假設(shè)fun2拿到了鎖,然后調(diào)用fun1又要去拿鎖,又不是recursive的,那么就會hang在fun1里邊。
?
std::time_mutex
官方文檔是這么說的:
recursive_timed_mutex 是同步原語,能用于保護(hù)共享數(shù)據(jù)免受從多個線程同時訪問。
以類似 std::recursive_mutex 的方式, recursive_timed_mutex 提供排他性遞歸所有權(quán)語義。另外, recursive_timed_mutex 通過 try_lock_for 與 try_lock_until 方法,提供帶時限地試圖要求 recursive_timed_mutex 所有權(quán)的能力。
recursive_timed_mutex 類滿足定時互斥體 (TimedMutex) 和標(biāo)準(zhǔn)布局類型 (StandardLayoutType) 的所有要求。
?
換成人話說:
std::time_mutex 比 std::mutex 多了兩個成員函數(shù),try_lock_for(),try_lock_until()。
try_lock_for 函數(shù)接受一個時間范圍,表示在這一段時間范圍之內(nèi)線程如果沒有獲得鎖則被阻塞住(與 std::mutex 的 try_lock() 不同,try_lock 如果被調(diào)用時沒有獲得鎖則直接返回 false),如果在此期間其他線程釋放了鎖,則該線程可以獲得對互斥量的鎖,如果超時(即在指定時間內(nèi)還是沒有獲得鎖),則返回 false。
try_lock_until 函數(shù)則接受一個時間點(diǎn)作為參數(shù),在指定時間點(diǎn)未到來之前線程如果沒有獲得鎖則被阻塞住,如果在此期間其他線程釋放了鎖,則該線程可以獲得對互斥量的鎖,如果超時(即在指定時間內(nèi)還是沒有獲得鎖),則返回 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。
總結(jié)
以上是生活随笔為你收集整理的std::mutex的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lambda 和 std::functi
- 下一篇: std::future和std::pro