這篇“C++11中如何使用Lock實(shí)現(xiàn)并發(fā)”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“C++11中如何使用Lock實(shí)現(xiàn)并發(fā)”文章吧。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、樂都網(wǎng)站維護(hù)、網(wǎng)站推廣。C++11 標(biāo)準(zhǔn)為我們提供了兩種基本的鎖類型,分別如下:
std::lock_guard,與 Mutex RAII 相關(guān),方便線程對(duì)互斥量上鎖。
std::unique_lock,與 Mutex RAII 相關(guān),方便線程對(duì)互斥量上鎖,但提供了更好的上鎖和解鎖控制。
另外還提供了幾個(gè)與鎖類型相關(guān)的 Tag 類,分別如下:
std::adopt_lock_t,一個(gè)空的標(biāo)記類,定義如下:
struct adopt_lock_t {};
該類型的常量對(duì)象adopt_lock(adopt_lock 是一個(gè)常量對(duì)象,定義如下:
constexpr adopt_lock_t adopt_lock {};,// constexpr 是 C++11 中的新關(guān)鍵字)
通常作為參數(shù)傳入給 unique_lock 或 lock_guard 的構(gòu)造函數(shù)。
std::defer_lock_t,一個(gè)空的標(biāo)記類,定義如下:
struct defer_lock_t {};
該類型的常量對(duì)象 defer_lock(defer_lock 是一個(gè)常量對(duì)象,定義如下:
constexpr defer_lock_t defer_lock {};,// constexpr 是 C++11 中的新關(guān)鍵字)
通常作為參數(shù)傳入給 unique_lock 或 lock_guard 的構(gòu)造函數(shù)。
std::try_to_lock_t,一個(gè)空的標(biāo)記類,定義如下:
struct try_to_lock_t {};
該類型的常量對(duì)象 try_to_lock(try_to_lock 是一個(gè)常量對(duì)象,定義如下:
constexpr try_to_lock_t try_to_lock {};,// constexpr 是 C++11 中的新關(guān)鍵字)
通常作為參數(shù)傳入給 unique_lock 或 lock_guard 的構(gòu)造函數(shù)。后面我們會(huì)詳細(xì)介紹以上三種 Tag 類型在配合 lock_gurad 與 unique_lock 使用時(shí)的區(qū)別。
std::lock_guard 介紹
std::lock_gurad 是 C++11 中定義的模板類。定義如下:
template <class Mutex> class lock_guard;
lock_guard 對(duì)象通常用于管理某個(gè)鎖(Lock)對(duì)象,因此與 Mutex RAII 相關(guān),方便線程對(duì)互斥量上鎖,即在某個(gè) lock_guard 對(duì)象的聲明周期內(nèi),它所管理的鎖對(duì)象會(huì)一直保持上鎖狀態(tài);而 lock_guard 的生命周期結(jié)束之后,它所管理的鎖對(duì)象會(huì)被解鎖(注:類似 shared_ptr 等智能指針管理動(dòng)態(tài)分配的內(nèi)存資源 )。
模板參數(shù) Mutex 代表互斥量類型,例如 std::mutex 類型,它應(yīng)該是一個(gè)基本的 BasicLockable 類型,標(biāo)準(zhǔn)庫(kù)中定義幾種基本的 BasicLockable 類型,分別 std::mutex, std::recursive_mutex, std::timed_mutex,std::recursive_timed_mutex (以上四種類型均已在上一篇博客中介紹)以及 std::unique_lock(本文后續(xù)會(huì)介紹 std::unique_lock)。(注:BasicLockable 類型的對(duì)象只需滿足兩種操作,lock 和 unlock,另外還有 Lockable 類型,在 BasicLockable 類型的基礎(chǔ)上新增了 try_lock 操作,因此一個(gè)滿足 Lockable 的對(duì)象應(yīng)支持三種操作:lock,unlock 和 try_lock;最后還有一種 TimedLockable 對(duì)象,在 Lockable 類型的基礎(chǔ)上又新增了 try_lock_for 和 try_lock_until 兩種操作,因此一個(gè)滿足 TimedLockable 的對(duì)象應(yīng)支持五種操作:lock, unlock, try_lock, try_lock_for, try_lock_until)。
在 lock_guard 對(duì)象構(gòu)造時(shí),傳入的 Mutex 對(duì)象(即它所管理的 Mutex 對(duì)象)會(huì)被當(dāng)前線程鎖住。在lock_guard 對(duì)象被析構(gòu)時(shí),它所管理的 Mutex 對(duì)象會(huì)自動(dòng)解鎖,由于不需要程序員手動(dòng)調(diào)用 lock 和 unlock 對(duì) Mutex 進(jìn)行上鎖和解鎖操作,因此這也是最簡(jiǎn)單安全的上鎖和解鎖方式,尤其是在程序拋出異常后先前已被上鎖的 Mutex 對(duì)象可以正確進(jìn)行解鎖操作,極大地簡(jiǎn)化了程序員編寫與 Mutex 相關(guān)的異常處理代碼。
值得注意的是,lock_guard 對(duì)象并不負(fù)責(zé)管理 Mutex 對(duì)象的生命周期,lock_guard 對(duì)象只是簡(jiǎn)化了 Mutex 對(duì)象的上鎖和解鎖操作,方便線程對(duì)互斥量上鎖,即在某個(gè) lock_guard 對(duì)象的聲明周期內(nèi),它所管理的鎖對(duì)象會(huì)一直保持上鎖狀態(tài);而 lock_guard 的生命周期結(jié)束之后,它所管理的鎖對(duì)象會(huì)被解鎖。
std::lock_guard 構(gòu)造函數(shù)
lock_guard 構(gòu)造函數(shù)如下表所示:
locking (1) | explicit lock_guard (mutex_type& m); |
---|---|
adopting (2) | lock_guard (mutex_type& m, adopt_lock_t tag); |
copy [deleted](3) | lock_guard (const lock_guard&) = delete; |
locking 初始化
lock_guard 對(duì)象管理 Mutex 對(duì)象 m,并在構(gòu)造時(shí)對(duì) m 進(jìn)行上鎖(調(diào)用 m.lock())。
adopting初始化
lock_guard 對(duì)象管理 Mutex 對(duì)象 m,與 locking 初始化(1) 不同的是, Mutex 對(duì)象 m 已被當(dāng)前線程鎖住。
拷貝構(gòu)造
lock_guard 對(duì)象的拷貝構(gòu)造和移動(dòng)構(gòu)造(move construction)均被禁用,因此 lock_guard 對(duì)象不可被拷貝構(gòu)造或移動(dòng)構(gòu)造。
我們來(lái)看一個(gè)簡(jiǎn)單的例子(參考):
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::lock_guard, std::adopt_lock std::mutex mtx; // mutex for critical section void print_thread_id (int id) { mtx.lock(); std::lock_guard<std::mutex> lck(mtx, std::adopt_lock); std::cout << "thread #" << id << '\n'; } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_thread_id,i+1); for (auto& th : threads) th.join(); return 0; }
在 print_thread_id 中,我們首先對(duì) mtx 進(jìn)行上鎖操作(mtx.lock();),然后用 mtx 對(duì)象構(gòu)造一個(gè) lock_guard 對(duì)象(std::lock_guard<std::mutex> lck(mtx, std::adopt_lock);),注意此時(shí) Tag 參數(shù)為 std::adopt_lock,表明當(dāng)前線程已經(jīng)獲得了鎖,此后 mtx 對(duì)象的解鎖操作交由 lock_guard 對(duì)象 lck 來(lái)管理,在 lck 的生命周期結(jié)束之后,mtx 對(duì)象會(huì)自動(dòng)解鎖。lock_guard 較大的特點(diǎn)就是安全易于使用,請(qǐng)看下面例子(參考),在異常拋出的時(shí)候通過(guò) lock_guard 對(duì)象管理的 Mutex 可以得到正確地解鎖。
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::lock_guard #include <stdexcept> // std::logic_error std::mutex mtx; void print_even (int x) { if (x%2==0) std::cout << x << " is even\n"; else throw (std::logic_error("not even")); } void print_thread_id (int id) { try { // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception: std::lock_guard<std::mutex> lck (mtx); print_even(id); } catch (std::logic_error&) { std::cout << "[exception caught]\n"; } } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_thread_id,i+1); for (auto& th : threads) th.join(); return 0; }
std::unique_lock 介紹
但是 lock_guard 較大的缺點(diǎn)也是簡(jiǎn)單,沒有給程序員提供足夠的靈活度,因此,C++11 標(biāo)準(zhǔn)中定義了另外一個(gè)與 Mutex RAII 相關(guān)類 unique_lock,該類與 lock_guard 類相似,也很方便線程對(duì)互斥量上鎖,但它提供了更好的上鎖和解鎖控制。
顧名思義,unique_lock 對(duì)象以獨(dú)占所有權(quán)的方式( unique owership)管理 mutex 對(duì)象的上鎖和解鎖操作,所謂獨(dú)占所有權(quán),就是沒有其他的 unique_lock 對(duì)象同時(shí)擁有某個(gè) mutex 對(duì)象的所有權(quán)。
在構(gòu)造(或移動(dòng)(move)賦值)時(shí),unique_lock 對(duì)象需要傳遞一個(gè) Mutex 對(duì)象作為它的參數(shù),新創(chuàng)建的 unique_lock 對(duì)象負(fù)責(zé)傳入的 Mutex 對(duì)象的上鎖和解鎖操作。
std::unique_lock 對(duì)象也能保證在其自身析構(gòu)時(shí)它所管理的 Mutex 對(duì)象能夠被正確地解鎖(即使沒有顯式地調(diào)用 unlock 函數(shù))。因此,和 lock_guard 一樣,這也是一種簡(jiǎn)單而又安全的上鎖和解鎖方式,尤其是在程序拋出異常后先前已被上鎖的 Mutex 對(duì)象可以正確進(jìn)行解鎖操作,極大地簡(jiǎn)化了程序員編寫與 Mutex 相關(guān)的異常處理代碼。
值得注意的是,unique_lock 對(duì)象同樣也不負(fù)責(zé)管理 Mutex 對(duì)象的生命周期,unique_lock 對(duì)象只是簡(jiǎn)化了 Mutex 對(duì)象的上鎖和解鎖操作,方便線程對(duì)互斥量上鎖,即在某個(gè) unique_lock 對(duì)象的聲明周期內(nèi),它所管理的鎖對(duì)象會(huì)一直保持上鎖狀態(tài);而 unique_lock 的生命周期結(jié)束之后,它所管理的鎖對(duì)象會(huì)被解鎖,這一點(diǎn)和 lock_guard 類似,但 unique_lock 給程序員提供了更多的自由,我會(huì)在下面的內(nèi)容中給大家介紹 unique_lock 的用法。
另外,與 lock_guard 一樣,模板參數(shù) Mutex 代表互斥量類型,例如 std::mutex 類型,它應(yīng)該是一個(gè)基本的 BasicLockable 類型,標(biāo)準(zhǔn)庫(kù)中定義幾種基本的 BasicLockable 類型,分別 std::mutex, std::recursive_mutex, std::timed_mutex,std::recursive_timed_mutex (以上四種類型均已在上一篇博客中介紹)以及 std::unique_lock(本文后續(xù)會(huì)介紹 std::unique_lock)。(注:BasicLockable 類型的對(duì)象只需滿足兩種操作,lock 和 unlock,另外還有 Lockable 類型,在 BasicLockable 類型的基礎(chǔ)上新增了 try_lock 操作,因此一個(gè)滿足 Lockable 的對(duì)象應(yīng)支持三種操作:lock,unlock 和 try_lock;最后還有一種 TimedLockable 對(duì)象,在 Lockable 類型的基礎(chǔ)上又新增了 try_lock_for 和 try_lock_until 兩種操作,因此一個(gè)滿足 TimedLockable 的對(duì)象應(yīng)支持五種操作:lock, unlock, try_lock, try_lock_for, try_lock_until)。
std::unique_lock 構(gòu)造函數(shù)
std::unique_lock 的構(gòu)造函數(shù)的數(shù)目相對(duì)來(lái)說(shuō)比 std::lock_guard 多,其中一方面也是因?yàn)?std::unique_lock 更加靈活,從而在構(gòu)造 std::unique_lock 對(duì)象時(shí)可以接受額外的參數(shù)??偟貋?lái)說(shuō),std::unique_lock 構(gòu)造函數(shù)如下:
default (1) | unique_lock() noexcept; |
---|---|
locking (2) | explicit unique_lock(mutex_type& m); |
try-locking (3) | unique_lock(mutex_type& m, try_to_lock_t tag); |
deferred (4) | unique_lock(mutex_type& m, defer_lock_t tag) noexcept; |
adopting (5) | unique_lock(mutex_type& m, adopt_lock_t tag); |
locking for (6) | template <class Rep, class Period> unique_lock(mutex_type& m, const chrono::duration<Rep,Period>& rel_time); |
locking until (7) | template <class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock,Duration>& abs_time); |
copy [deleted] (8) | unique_lock(const unique_lock&) = delete; |
move (9) | unique_lock(unique_lock&& x); |
下面我們來(lái)分別介紹以上各個(gè)構(gòu)造函數(shù):
(1) 默認(rèn)構(gòu)造函數(shù)
新創(chuàng)建的 unique_lock 對(duì)象不管理任何 Mutex 對(duì)象。
(2) locking 初始化
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象 m,并嘗試調(diào)用 m.lock() 對(duì) Mutex 對(duì)象進(jìn)行上鎖,如果此時(shí)另外某個(gè) unique_lock 對(duì)象已經(jīng)管理了該 Mutex 對(duì)象 m,則當(dāng)前線程將會(huì)被阻塞。
(3) try-locking 初始化
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象 m,并嘗試調(diào)用 m.try_lock() 對(duì) Mutex 對(duì)象進(jìn)行上鎖,但如果上鎖不成功,并不會(huì)阻塞當(dāng)前線程。
(4) deferred 初始化
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象 m,但是在初始化的時(shí)候并不鎖住 Mutex 對(duì)象。 m 應(yīng)該是一個(gè)沒有當(dāng)前線程鎖住的 Mutex 對(duì)象。
(5) adopting 初始化
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象 m, m 應(yīng)該是一個(gè)已經(jīng)被當(dāng)前線程鎖住的 Mutex 對(duì)象。(并且當(dāng)前新創(chuàng)建的 unique_lock 對(duì)象擁有對(duì)鎖(Lock)的所有權(quán))。
(6) locking 一段時(shí)間(duration)
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象 m,并試圖通過(guò)調(diào)用 m.try_lock_for(rel_time) 來(lái)鎖住 Mutex 對(duì)象一段時(shí)間(rel_time)。
(7) locking 直到某個(gè)時(shí)間點(diǎn)(time point)
新創(chuàng)建的 unique_lock 對(duì)象管理 Mutex 對(duì)象m,并試圖通過(guò)調(diào)用 m.try_lock_until(abs_time) 來(lái)在某個(gè)時(shí)間點(diǎn)(abs_time)之前鎖住 Mutex 對(duì)象。
(8) 拷貝構(gòu)造 [被禁用]
unique_lock 對(duì)象不能被拷貝構(gòu)造。
(9) 移動(dòng)(move)構(gòu)造
新創(chuàng)建的 unique_lock 對(duì)象獲得了由 x 所管理的 Mutex 對(duì)象的所有權(quán)(包括當(dāng)前 Mutex 的狀態(tài))。調(diào)用 move 構(gòu)造之后, x 對(duì)象如同通過(guò)默認(rèn)構(gòu)造函數(shù)所創(chuàng)建的,就不再管理任何 Mutex 對(duì)象了。
綜上所述,由 (2) 和 (5) 創(chuàng)建的 unique_lock 對(duì)象通常擁有 Mutex 對(duì)象的鎖。而通過(guò) (1) 和 (4) 創(chuàng)建的則不會(huì)擁有鎖。通過(guò) (3),(6) 和 (7) 創(chuàng)建的 unique_lock 對(duì)象,則在 lock 成功時(shí)獲得鎖。
關(guān)于unique_lock 的構(gòu)造函數(shù),請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::lock, std::unique_lock // std::adopt_lock, std::defer_lock std::mutex foo,bar; void task_a () { std::lock (foo,bar); // simultaneous lock (prevents deadlock) std::unique_lock<std::mutex> lck1 (foo,std::adopt_lock); std::unique_lock<std::mutex> lck2 (bar,std::adopt_lock); std::cout << "task a\n"; // (unlocked automatically on destruction of lck1 and lck2) } void task_b () { // foo.lock(); bar.lock(); // replaced by: std::unique_lock<std::mutex> lck1, lck2; lck1 = std::unique_lock<std::mutex>(bar,std::defer_lock); lck2 = std::unique_lock<std::mutex>(foo,std::defer_lock); std::lock (lck1,lck2); // simultaneous lock (prevents deadlock) std::cout << "task b\n"; // (unlocked automatically on destruction of lck1 and lck2) } int main () { std::thread th2 (task_a); std::thread th3 (task_b); th2.join(); th3.join(); return 0; }
std::unique_lock 移動(dòng)(move assign)賦值操作
std::unique_lock 支持移動(dòng)賦值(move assignment),但是普通的賦值被禁用了,
move (1) | unique_lock& operator= (unique_lock&& x) noexcept; |
---|---|
copy [deleted] (2) | unique_lock& operator= (const unique_lock&) = delete; |
移動(dòng)賦值(move assignment)之后,由 x 所管理的 Mutex 對(duì)象及其狀態(tài)將會(huì)被新的 std::unique_lock 對(duì)象取代。
如果被賦值的對(duì)象之前已經(jīng)獲得了它所管理的 Mutex 對(duì)象的鎖,則在移動(dòng)賦值(move assignment)之前會(huì)調(diào)用 unlock 函數(shù)釋放它所占有的鎖。
調(diào)用移動(dòng)賦值(move assignment)之后, x 對(duì)象如同通過(guò)默認(rèn)構(gòu)造函數(shù)所創(chuàng)建的,也就不再管理任何 Mutex 對(duì)象了。請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock std::mutex mtx; // mutex for critical section void print_fifty (char c) { std::unique_lock<std::mutex> lck; // default-constructed lck = std::unique_lock<std::mutex>(mtx); // move-assigned for (int i=0; i<50; ++i) { std::cout << c; } std::cout << '\n'; } int main () { std::thread th2 (print_fifty,'*'); std::thread th3 (print_fifty,'$'); th2.join(); th3.join(); return 0; }
std::unique_lock 主要成員函數(shù)
本節(jié)我們來(lái)看看 std::unique_lock 的主要成員函數(shù)。由于 std::unique_lock 比 std::lock_guard 操作靈活,因此它提供了更多成員函數(shù)。具體分類如下:
上鎖/解鎖操作:lock,try_lock,try_lock_for,try_lock_until 和 unlock
修改操作:移動(dòng)賦值(move assignment)(前面已經(jīng)介紹過(guò)了),交換(swap)(與另一個(gè) std::unique_lock 對(duì)象交換它們所管理的 Mutex 對(duì)象的所有權(quán)),釋放(release)(返回指向它所管理的 Mutex 對(duì)象的指針,并釋放所有權(quán))
獲取屬性操作:owns_lock(返回當(dāng)前 std::unique_lock 對(duì)象是否獲得了鎖)、operator bool()(與 owns_lock 功能相同,返回當(dāng)前 std::unique_lock 對(duì)象是否獲得了鎖)、mutex(返回當(dāng)前 std::unique_lock 對(duì)象所管理的 Mutex 對(duì)象的指針)。
std::unique_lock::lock請(qǐng)看下面例子(參考):
上鎖操作,調(diào)用它所管理的 Mutex 對(duì)象的 lock 函數(shù)。如果在調(diào)用 Mutex 對(duì)象的 lock 函數(shù)時(shí)該 Mutex 對(duì)象已被另一線程鎖住,則當(dāng)前線程會(huì)被阻塞,直到它獲得了鎖。
該函數(shù)返回時(shí),當(dāng)前的 unique_lock 對(duì)象便擁有了它所管理的 Mutex 對(duì)象的鎖。如果上鎖操作失敗,則拋出 system_error 異常。
// unique_lock::lock/unlock #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::defer_lock std::mutex mtx; // mutex for critical section void print_thread_id (int id) { std::unique_lock<std::mutex> lck (mtx,std::defer_lock); // critical section (exclusive access to std::cout signaled by locking lck): lck.lock(); std::cout << "thread #" << id << '\n'; lck.unlock(); } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_thread_id,i+1); for (auto& th : threads) th.join(); return 0; }
std::unique_lock::try_lock
上鎖操作,調(diào)用它所管理的 Mutex 對(duì)象的 try_lock 函數(shù),如果上鎖成功,則返回 true,否則返回 false。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <vector> // std::vector #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::defer_lock std::mutex mtx; // mutex for critical section void print_star () { std::unique_lock<std::mutex> lck(mtx,std::defer_lock); // print '*' if successfully locked, 'x' otherwise: if (lck.try_lock()) std::cout << '*'; else std::cout << 'x'; } int main () { std::vector<std::thread> threads; for (int i=0; i<500; ++i) threads.emplace_back(print_star); for (auto& x: threads) x.join(); return 0; }
std::unique_lock::try_lock_for
上鎖操作,調(diào)用它所管理的 Mutex 對(duì)象的 try_lock_for 函數(shù),如果上鎖成功,則返回 true,否則返回 false。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <chrono> // std::chrono::milliseconds #include <thread> // std::thread #include <mutex> // std::timed_mutex, std::unique_lock, std::defer_lock std::timed_mutex mtx; void fireworks () { std::unique_lock<std::timed_mutex> lck(mtx,std::defer_lock); // waiting to get a lock: each thread prints "-" every 200ms: while (!lck.try_lock_for(std::chrono::milliseconds(200))) { std::cout << "-"; } // got a lock! - wait for 1s, then this thread prints "*" std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << "*\n"; } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(fireworks); for (auto& th : threads) th.join(); return 0; }
std::unique_lock::try_lock_until
上鎖操作,調(diào)用它所管理的 Mutex 對(duì)象的 try_lock_for 函數(shù),如果上鎖成功,則返回 true,否則返回 false。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <chrono> // std::chrono::milliseconds #include <thread> // std::thread #include <mutex> // std::timed_mutex, std::unique_lock, std::defer_lock std::timed_mutex mtx; void fireworks () { std::unique_lock<std::timed_mutex> lck(mtx,std::defer_lock); // waiting to get a lock: each thread prints "-" every 200ms: while (!lck.try_lock_for(std::chrono::milliseconds(200))) { std::cout << "-"; } // got a lock! - wait for 1s, then this thread prints "*" std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << "*\n"; } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(fireworks); for (auto& th : threads) th.join(); return 0; }
std::unique_lock::unlock
解鎖操作,調(diào)用它所管理的 Mutex 對(duì)象的 unlock 函數(shù)。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::defer_lock std::mutex mtx; // mutex for critical section void print_thread_id (int id) { std::unique_lock<std::mutex> lck (mtx,std::defer_lock); // critical section (exclusive access to std::cout signaled by locking lck): lck.lock(); std::cout << "thread #" << id << '\n'; lck.unlock(); } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_thread_id,i+1); for (auto& th : threads) th.join(); return 0; }
std::unique_lock::release
返回指向它所管理的 Mutex 對(duì)象的指針,并釋放所有權(quán)。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <vector> // std::vector #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock std::mutex mtx; int count = 0; void print_count_and_unlock (std::mutex* p_mtx) { std::cout << "count: " << count << '\n'; p_mtx->unlock(); } void task() { std::unique_lock<std::mutex> lck(mtx); ++count; print_count_and_unlock(lck.release()); } int main () { std::vector<std::thread> threads; for (int i=0; i<10; ++i) threads.emplace_back(task); for (auto& x: threads) x.join(); return 0; }
std::unique_lock::owns_lock
返回當(dāng)前 std::unique_lock 對(duì)象是否獲得了鎖。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <vector> // std::vector #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::try_to_lock std::mutex mtx; // mutex for critical section void print_star () { std::unique_lock<std::mutex> lck(mtx,std::try_to_lock); // print '*' if successfully locked, 'x' otherwise: if (lck.owns_lock()) std::cout << '*'; else std::cout << 'x'; } int main () { std::vector<std::thread> threads; for (int i=0; i<500; ++i) threads.emplace_back(print_star); for (auto& x: threads) x.join(); return 0; }
std::unique_lock::operator bool()
與 owns_lock 功能相同,返回當(dāng)前 std::unique_lock 對(duì)象是否獲得了鎖。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <vector> // std::vector #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::try_to_lock std::mutex mtx; // mutex for critical section void print_star () { std::unique_lock<std::mutex> lck(mtx,std::try_to_lock); // print '*' if successfully locked, 'x' otherwise: if (lck) std::cout << '*'; else std::cout << 'x'; } int main () { std::vector<std::thread> threads; for (int i=0; i<500; ++i) threads.emplace_back(print_star); for (auto& x: threads) x.join(); return 0; }
std::unique_lock::mutex
返回當(dāng)前 std::unique_lock 對(duì)象所管理的 Mutex 對(duì)象的指針。
請(qǐng)看下面例子(參考):
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock, std::defer_lock class MyMutex : public std::mutex { int _id; public: MyMutex (int id) : _id(id) {} int id() {return _id;} }; MyMutex mtx (101); void print_ids (int id) { std::unique_lock<MyMutex> lck (mtx); std::cout << "thread #" << id << " locked mutex " << lck.mutex()->id() << '\n'; } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_ids,i+1); for (auto& th : threads) th.join(); return 0; }
以上就是關(guān)于“C++11中如何使用Lock實(shí)現(xiàn)并發(fā)”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站題目:C++11中如何使用Lock實(shí)現(xiàn)并發(fā)-創(chuàng)新互聯(lián)
本文鏈接:http://www.rwnh.cn/article26/ddspjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、搜索引擎優(yōu)化、營(yíng)銷型網(wǎng)站建設(shè)、商城網(wǎng)站、定制網(wǎng)站、網(wǎng)站內(nèi)鏈
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容