真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【并發(fā)編程九】c++線程同步——互斥(mutex)-創(chuàng)新互聯(lián)

【并發(fā)編程九】c++線程同步——互斥(mutex)
  • 一、互斥
    • 1、mutex
      • 1.1、mutex
      • 1.2、 lock_guard
      • 1.3、 RAII
    • 2、std::recursive_mutex
    • 3、std::shared_mutex、std::shared_lock、std::unique_lock
    • 4、std::scoped_lock
  • 二、條件變量
  • 三、future
  • 四、信號量

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名與空間、網(wǎng)站空間、營銷軟件、網(wǎng)站建設、富裕網(wǎng)站維護、網(wǎng)站推廣。
  • 簡介:
    本篇文章,我們詳細的介紹下c++標準庫提供的線程同步方法中的第一個——互斥(mutex)。
一、互斥
  • 互斥算法避免多個線程同時訪問共享資源。這會避免數(shù)據(jù)競爭,并提供線程間的同步支持。
    前四個定義于頭文件,后兩個定義于頭文件
互斥類型解釋
mutex(C++11)提供基本互斥設施(類)
timed_mutex(C++11)提供互斥設施,實現(xiàn)有時限鎖定(類)
recursive_mutex(C++11)提供能被同一線程遞歸鎖定的互斥設施(類)
recursive_timed_mutex(C++11)
提供能被同一線程遞歸鎖定的互斥設施,并實現(xiàn)有時限鎖定(類)
shared_mutex(C++17)提供共享互斥設施(類)
shared_timed_mutex(C++14)提供共享互斥設施并實現(xiàn)有時限鎖定(類)
  • 通用互斥管理
    定義于頭文件
互斥管理解釋
lock_guard(C++11)實現(xiàn)嚴格基于作用域的互斥體所有權包裝器(類模板)
scoped_lock (C++17)用于多個互斥體的免死鎖 RAII 封裝器(類模板)
unique_lock (C++11)實現(xiàn)可移動的互斥體所有權包裝器(類模板)
shared_lock(C++14)實現(xiàn)可移動的共享互斥體所有權封裝器(類模板)
defer_lock_t(C++11)
try_to_lock_t(C++11)
adopt_lock_t(C++11)
用于指定鎖定策略的標簽類型(類)
defer_lock(C++11)
try_to_lock(C++11)
adopt_lock(C++11)
用于指定鎖定策略的標簽常量(常量)
1、mutex 1.1、mutex
  • mutex 類是能用于保護共享數(shù)據(jù)免受從多個線程同時訪問的同步原語。
  • 通常不直接使用 std::mutex ,我們通常使用 std::unique_lock 、 std::lock_guard 或 std::scoped_lock (C++17 起)以更加異常安全的方式管理鎖定。
  • 此示例展示 mutex 能如何用于在保護共享于二個線程間的 std::map 。
  • 如果不會map加鎖,我們輸出的map中的值時,可能只有一個值。
1.2、 lock_guard
  • 類 lock_guard 是互斥體包裝器,為在作用域塊期間占有互斥提供便利 RAII 風格機制。
  • 創(chuàng)建 lock_guard 對象時,它試圖接收給定互斥的所有權。控制離開創(chuàng)建 lock_guard 對象的作用域時,銷毀lock_guard 并釋放互斥。
  • lock_guard 類不可復制。
1.3、 RAII
  • 資源獲取即初始化(Resource Acquisition Is Initialization),或稱 RAII,是一種 C++ 編程技術,它將必須在使用前請求的資源(分配的堆內存、執(zhí)行線程、打開的套接字、打開的文件、鎖定的互斥體、磁盤空間、數(shù)據(jù)庫連接等——任何存在受限供給中的事物)的生命周期綁定與一個對象的生存期相綁定。
#include#include#include#include#include#includestd::mapg_pages;
std::mutex g_pages_mutex;

void save_page(const std::string& url)
{// 模擬長頁面讀取
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::string result = "fake content";

    std::lock_guardguard(g_pages_mutex);
    g_pages[url] = result;
}

int main()
{std::thread t1(save_page, "http://foo");
    std::thread t2(save_page, "http://bar");
    t1.join();
    t2.join();

    // 現(xiàn)在訪問g_pages是安全的,因為線程t1/t2生命周期已結束
    for (const auto& pair : g_pages) {std::cout<< pair.first<< " =>"<< pair.second<< '\n';
    }
}

在這里插入圖片描述

2、std::recursive_mutex
  • recursive_mutex 類是同步原語,能用于保護共享數(shù)據(jù)免受從個多線程同時訪問。
  • recursive_mutex 提供排他性遞歸所有權語義:
  • recursive_mutex 的使用場景之一是保護類中的共享狀態(tài),而類的成員函數(shù)可能相互調用
  • 用法:
    recursive_mutex的用處和mutex差不多,用于限制多線程同時訪問同一個變量,用來加鎖,保證多個線程,同一時刻只能有一個線程在修改變量;和mutex不同的時,recursive_mutex可以允許同一個線程遞歸的去加鎖,線程只有加鎖次數(shù)和釋放次數(shù)相同時,才會釋放變量的控制權;例如下面的fun2中調用了fun1,但是fun1和fun2中都加了鎖,如果使用mutex,在fun1加鎖,在fun2中再次加鎖,就會造成死鎖;所以recursive_mutex可以避免遞歸嵌套調用時,造成的死鎖問題;遞歸調用不會死鎖,同一線程使用recursive_mutex加鎖次數(shù)和解鎖次數(shù)相等時釋放控制權;
#include#include#includeclass X {std::recursive_mutex m;
    std::string shared;
public:
    void fun1() {std::lock_guardlk(m);
        shared = "fun1";
        std::cout<< "in fun1, shared variable is now "<< shared<< '\n';
    }
    void fun2() {std::lock_guardlk(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();
}

在這里插入圖片描述

3、std::shared_mutex、std::shared_lock、std::unique_lock

C++17 std::shared_mutex的替代方案boost::shared_mutex
shared_mutex 類,結合 unique_lock 與 shared_lock 的使用,可以實現(xiàn)讀寫鎖。

通常讀寫鎖需要完成以下功能:

  • 1.當 data 被線程A讀取時,其他線程仍可以進行讀取卻不能寫入
  • 2.當 data 被線程A寫入時,其他線程既不能讀取也不能寫入

對應于功能1,2我們可以這樣來描述:

  • 1.當線程A獲得共享鎖時,其他線程仍可以獲得共享鎖但不能獲得獨占鎖
  • 2.當線程A獲得獨占鎖時,其他線程既不能獲得共享鎖也不能獲得獨占鎖
#include#include#includeusing namespace std;

typedef std::shared_lockread_lock;
typedef std::unique_lockwrite_lock;

std::shared_mutex read_write_mutex;
int32_t g_data =0;

//線程A,讀data
void fun1()
{for (size_t i = 0; i< 10; i++)
    {read_lock rlock(read_write_mutex);
        cout<< "t1:g_data="<< g_data<< endl;
    }
}

//線程B,讀data
void fun2()
{for (size_t i = 0; i< 10; i++)
    {read_lock rlock(read_write_mutex);
        std::cout<<"t2:g_data="<< g_data<< endl;
    }
}

//線程C,寫data
void fun3()
{for (size_t i = 0; i< 10; i++)
    {write_lock rlock(read_write_mutex);
        g_data++;
        std::cout<< "t3:g_data="<< g_data<< endl;
    }
}

int main()
{thread t3(fun3);
    thread t1(fun1);
    thread t2(fun2);
    
 
    t1.join();
    t2.join();
    t3.join();
}

輸出如下
在這里插入圖片描述

結果說明:

  • 線程1和線程2可以同時讀,
    (由于io是進程間共享的,可以看到線程1和2同時操作時,在換行endl還沒有輸出完,兩個線程出現(xiàn)了搶占io資源,所以,我們看到了t1和t2輸出到了同一行)
  • 在線程1或者線程2加了鎖讀時,我們的線程3不可以寫的。(所以,我們看不到t3和t1或者t2在同一行)
  • 線程3寫入時,不允許線程1和線程3寫入。(所以,我們看不到t3和t1或者t2在同一行)

簡單總結下

  • std::shared_lock是讀鎖,被鎖后仍允許其他線程執(zhí)行同樣被shared_lock的代碼,
    當data被線程A讀取時,仍允許其它線程讀取data,但是不能寫入。
  • std::unique_lock是寫鎖。被鎖后不允許其他線程執(zhí)行被shared_lock或unique_lock的代碼。
    在寫操作時,一般用這個,可以同時限制unique_lock的寫和share_lock的讀。
4、std::scoped_lock

lock_guard:更加靈活的鎖管理類模板,構造時是否加鎖是可選的,在對象析構時如果持有鎖會自動釋放鎖,所有權可以轉移。對象生命期內允許手動加鎖和釋放鎖。

scope_lock:嚴格基于作用域(scope-based)的鎖管理類模板,構造時是否加鎖是可選的(不加鎖時假定當前線程已經(jīng)獲得鎖的所有權),析構時自動釋放鎖,所有權不可轉移,對象生存期內不允許手動加鎖和釋放鎖。

share_lock:用于管理可轉移和共享所有權的互斥對象。

  • scope_lock和lock_guard相比,可以簡單的理解,在生命周期內,scope_lock不允許手動加鎖和釋放鎖,而lock_guard可以。

參考:
1、https://www.apiref.com/cpp-zh/cpp/thread.html
2、https://en.cppreference.com/w/cpp/thread
3、書籍《c++服務器開發(fā)精髓》——張遠龍

二、條件變量
  • 參見【并發(fā)編程十】c++線程同步——條件變量(condition_variable)
三、future
  • 參見【并發(fā)編程十一】c++線程同步——future
四、信號量
  • 參見【并發(fā)編程十二】c++線程同步——信號量(semaphore)

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


分享名稱:【并發(fā)編程九】c++線程同步——互斥(mutex)-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://weahome.cn/article/ddijcg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部