C++ scoped_lock,unique_lock,lock_guard

來源:互聯網
上載者:User

標籤:不同的   second   語義   post   處理   names   變化   grant   resource   

考慮互斥量的使用,最基本的代碼是:

 1 #include <iostream> 2 #include <thread> 3 #include <mutex>   4  5 std::mutex g_my_mutex; 6  7 std::lock_guard<std::mutex> make_lock() { 8     return std::lock_guard<std::mutex>(g_my_mutex); 9 }10 11 void workOnResource1() {12 13     for (int i = 0; i < 10000; ++i)14     {15         std::lock_guard<std::mutex> lk(g_my_mutex);16         --gi;17     }18 }19 20 void workOnResource2() {21 22     for (int i = 0; i < 10000; ++i)23     {24         auto lk = make_lock();25         ++gi;26     }27 }28 29 int main() {30 31     std::thread t1(workOnResource1);32     std::thread t2(workOnResource2);33 34     t1.join();35     t2.join();36     37     std::cout << "gi=" <<gi;38 }

這在很多例子裡都常見。等等,為什麼第8行編譯不過去?那是因為您沒有在C++17下編譯。std::lock_guard是禁止拷貝和移動的。C++17 granteed copy ellision允許第8行編譯通過。

比較一下,第24行和第15行,哪個更簡潔一些呢?

std::lock_guard還可以這樣用:

void workOnResource1() {    for (int i = 0; i < 10000; ++i)    {        g_my_mutex.lock();        std::lock_guard<std::mutex> lk(g_my_mutex, std::adopt_lock);        --gi;    }}

意思就是,當lk物件建構時,不去調用mutex::lock()。因為之前自己所持有的鎖已經lock了一次了(g_my_mutex.lock())。adopt就是這個意思的表達,英文的含義是收養。

當lk析構時,對g_my_mutex調用mutex::unlock,這一點沒有變化。

現在考慮unique_lock的用法:用於更複雜的互斥量操作上,例如:有逾時時間的加鎖。

#include <iostream>#include <thread>#include <mutex>          // std::mutex, std::lock_guard #include <chrono>using Ms = std::chrono::milliseconds;using namespace std;int gi = 0;std::timed_mutex g_my_mutex;std::lock_guard<std::timed_mutex> make_lock() {    return std::lock_guard<std::timed_mutex>(g_my_mutex);  //絕不能分行寫}void workOnResource1() {    for (int i = 0; i < 10000; ++i)    {        auto lk = make_lock();        ++gi;    }}std::unique_lock<std::timed_mutex> make_lock2() {    std::unique_lock<std::timed_mutex> lk(g_my_mutex, std::defer_lock);    return lk;  //故意分行寫}void workOnResource2() {    for (int i = 0; i < 10000; ++i)    {        auto lk = make_lock2();        while(lk.try_lock_for(Ms(100))==false){            std::cout << "lock fail. reason timeout. now retry...";        }        --gi;    }}int main() {    std::thread t1(workOnResource1);    std::thread t2(workOnResource2);    t1.join();    t2.join();        std::cout << "gi=" <<gi;}

unique_lock支援move語義,這樣它就能飛出{}之外了。像極了std::unique_ptr。同樣的,它也是RAII的,當析構時,調用mutex::unlock().

std::defer_lock是個全域變數,類型是std::defer_lock_t。顯然,它用於函數的重載解析時,選不同的函數執行的。defer_lock的意思是,暫時不對g_my_mutex調用任何加鎖動作。

為了證明,unique_lock是可以move的,可以這樣:

std::unique_lock<std::timed_mutex> lk(g_my_mutex, std::defer_lock);std::unique_lock<std::timed_mutex> lk2(std::move(lk));lk2.lock();

scoped_lock是C++17新引進的,在處理多個互斥量時,特別簡單:

參考:http://en.cppreference.com/w/cpp/thread/scoped_lock

C++ scoped_lock,unique_lock,lock_guard

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.