欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中多線程間共享數(shù)據(jù)詳解

 更新時(shí)間:2024年01月09日 11:03:21   作者:wingのpeterPen  
這篇文章主要為大家詳細(xì)介紹了C++中多線程間共享數(shù)據(jù)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在 C++ 中,我們可以通過構(gòu)造 std::mutex (mutual exclusion)的實(shí)例來創(chuàng)建互斥,調(diào)用成員函數(shù) lock() 對(duì)其加鎖,調(diào)用 unlock() 解鎖。但是不推薦直接調(diào)用成員函數(shù)的做法,因?yàn)檫@樣做,那我們就必須在該函數(shù)的每條路徑上都調(diào)用 unlock(),包括異常導(dǎo)致退出的路徑。取而代之,C++標(biāo)準(zhǔn)庫提供了類模板 std::lock_guard<>,針對(duì)互斥類融合RAII手法:在構(gòu)造的時(shí)候給互斥加鎖,在析構(gòu)時(shí)進(jìn)行解鎖,從而保證互斥總被正確解鎖。

std::mutex的基本用法

std::list<int> some_list;
std::mutex some_mutex;

void add_to_list(int new_value){
    std::lock_guard<std::mutex> guard(some_mutex);
	some_list.push_back(new_value);
}

bool list_contains(int value_to_find){
    std::lock_guard<std::mutex> guard(some_mutex);
    return std::find(some_list.begin(), some_list.end(), value_to_find) != some_list.end();
}

防范死鎖

防范死鎖的通常建議是,始終按相同順序?qū)蓚€(gè)互斥加鎖。若我們總是先鎖互斥A,再鎖互斥B,則永遠(yuǎn)不會(huì)發(fā)生死鎖。但是有時(shí)會(huì)出現(xiàn)一些棘手的問題,例如,一個(gè)函數(shù),其操作同一個(gè)類的兩個(gè)實(shí)例,交換它們內(nèi)部的數(shù)據(jù)為了保證并發(fā)時(shí),免受其他改動(dòng)的影響,需要對(duì)它們進(jìn)行加鎖,但是函數(shù)入?yún)⒌捻樞蚩梢愿淖?,即可以是swap(A,B)也可以是swap(B,A),當(dāng)同時(shí)發(fā)生這種情況時(shí),死鎖也會(huì)發(fā)生。因此需要一種方式來,來同時(shí)鎖住兩個(gè)互斥,而不是誰先誰后。即要求“全員共同成敗”(all-or-nothing,或全部成功鎖定,或沒獲取任何鎖并拋出異常)的語義。

使用 std::lock() 函數(shù),同時(shí)鎖住互斥。

class some_big_object;
void swap(some_big_object& lhs, some_big_object& rhs);

class X{
private:
	some_big_object some_detail;
	std::mutex m;

public:
	X(const some_big_object &sd):some_detail(sd){}

	friend void swap(X& lhs, X& rhs){
        if(&lhs == &rhs){
            return;
        }

        std::lock(lhs.m, rhs.m);
        std::lock_guard lock_a(lhs.m, std::adopt_lock);
        std::lock_guard lock_b(rhs.m, std::adopt_lock);

        swap(lhs.some_detail, rhs.some_detail);
    }
}

std::lock() 是一個(gè)函數(shù),并不像 RAII 類一樣,在析構(gòu)時(shí)進(jìn)行解鎖。因此需要借助 std::lock_guard 類型的對(duì)象,讓 std::mutex 在函數(shù)完成后進(jìn)行解鎖。std::adopt_lock 作為函數(shù)參數(shù),表示 std::mutex 已經(jīng)被鎖住了,讓std::lock_guard 類不需要在構(gòu)造函數(shù)中對(duì) std::mutex 進(jìn)行加鎖。C++ 17出現(xiàn)了 std::scoped_lock<> 模板類,其和 std::lock_guard<>完全等價(jià),只不過前者是可變參數(shù)模板,接受各種互斥型別作為模板參數(shù),還以多個(gè)互斥對(duì)象作為構(gòu)造函數(shù)的參數(shù)列表,除了這些其還有與 std::lock() 函數(shù)一樣的功能,因此可以改善上述代碼。

void swap(X& lhs, X& rhs){
    if(&lhs == &rhs){
            return;
    }

    std::scoped_lock guard(lhs.m, rhs.m);
    swap(lhs.some_detail, rhs.some_detail);
}

std::lock_guard 和 std::unique_lock

std::unique_lock 類支持在構(gòu)造時(shí)暫時(shí)不獲得鎖,在需要的時(shí)候手動(dòng)調(diào)用 lock(),而獲得鎖。其含有一個(gè)內(nèi)部標(biāo)志 __owns__(可以通過其成員函數(shù) owns_lock() 獲得),表明關(guān)聯(lián)的互斥目前是否正被該類的實(shí)例上鎖。假如 std::unique_lock 實(shí)例關(guān)聯(lián)的互斥的確上鎖了,則其析構(gòu)函數(shù)必須調(diào)用unlock();若不然,實(shí)例并未將關(guān)聯(lián)的互斥上鎖,便絕不能調(diào)用 unlock()。

初始化時(shí)保護(hù)共享數(shù)據(jù)

void undefined_behaviour_with_double_checked_locking()
{
    if(!resource_ptr){ //①
        std::lock_guard<std::mutex> lk(resource_mutex); // ②
        if(!resource_ptr){
            resource_ptr.reset(new some_resource);
        }
    }
    resource_ptr->do_something();
}

在雙重檢查鎖定模式中,一號(hào)線程執(zhí)行到①發(fā)現(xiàn)條件滿足(resource_ptr 為空),同時(shí)二號(hào)線程執(zhí)行到①也發(fā)現(xiàn)條件滿足,然后繼續(xù)執(zhí)行上鎖操作②,此時(shí)一號(hào)線程也會(huì)去執(zhí)行上鎖操作,但是resource_mutex上的鎖已經(jīng)被二號(hào)線程持有了,這樣就會(huì)發(fā)生數(shù)據(jù)競爭(當(dāng)然會(huì)發(fā)生惡性數(shù)據(jù)競爭的路徑不止這一條)。

為了解決這種情況,C++標(biāo)準(zhǔn)庫中提供了 std::onec_flag 類 和 std::call_once 類。

std::shared_ptr<some_resource> resource_ptr;
std::once_flag resource_flag;

void init_resource()
{
    resource_ptr.reset(new some_resource);
}

void foo()
{
    std::call_once(resource_flag, init_resource);
    resource_ptr->do_something();
}

保護(hù)讀多寫少的數(shù)據(jù)

C++ 17 標(biāo)準(zhǔn)庫提供了兩種新的互斥:std::shared_mutex 和 std::shared_timed_mutex(C++14就有了)。兩者的區(qū)別在于后者支持更多操作。

std::shared_mutex mutex;

// 獲取讀鎖(又叫共享鎖)
std::shared_lock read_lock(mutex);

// 獲取寫鎖(又叫排它鎖)
std::lock_guard write_lock(mutex);

假設(shè)共享鎖已經(jīng)被某些線程持有,若別的線程試圖獲取排他鎖,就會(huì)發(fā)生阻塞,直到這些線程全都釋放該共享鎖。反之,如果任一線程持有排他鎖,那么其他線程都無法獲取共享鎖或排它鎖,直到持鎖線程將排它鎖釋放為止。

到此這篇關(guān)于C++中多線程間共享數(shù)據(jù)詳解的文章就介紹到這了,更多相關(guān)C++共享數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何使用C++結(jié)合OpenCV進(jìn)行圖像處理與分類

    如何使用C++結(jié)合OpenCV進(jìn)行圖像處理與分類

    在計(jì)算機(jī)視覺領(lǐng)域,OpenCV與C++結(jié)合能高效處理和分類圖像,C++的高執(zhí)行效率適合大規(guī)模數(shù)據(jù)處理,OpenCV提供豐富的功能,如圖像預(yù)處理和機(jī)器學(xué)習(xí)算法,安裝OpenCV需要配置環(huán)境和添加庫文件,本文詳細(xì)介紹了使用C++和OpenCV進(jìn)行圖像分類的過程,包括使用SVM和深度學(xué)習(xí)模型
    2024-09-09
  • C/C++ Qt QThread線程組件的具體使用

    C/C++ Qt QThread線程組件的具體使用

    QThread庫是QT中提供的跨平臺(tái)多線程實(shí)現(xiàn)方案,本文詳細(xì)的介紹了Qt QThread線程組件的具體使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除

    C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)鄰接表頂點(diǎn)的刪除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++用read()和write()讀寫二進(jìn)制文件的超詳細(xì)教程

    C++用read()和write()讀寫二進(jìn)制文件的超詳細(xì)教程

    二進(jìn)制的文件肉眼我們是讀不懂的,如果通過二進(jìn)制的讀寫操作就可以讀懂,下面這篇文章主要給大家介紹了關(guān)于C++用read()和write()讀寫二進(jìn)制文件的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • C語言fprintf()函數(shù)和fscanf()函數(shù)的具體使用

    C語言fprintf()函數(shù)和fscanf()函數(shù)的具體使用

    本文主要介紹了C語言fprintf()函數(shù)和fscanf()函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳細(xì)分析C++ 多態(tài)和虛函數(shù)

    詳細(xì)分析C++ 多態(tài)和虛函數(shù)

    這篇文章主要介紹了C++ 多態(tài)和虛函數(shù)的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • VS2017+Qt5+Opencv3.4調(diào)用攝像頭拍照并存儲(chǔ)

    VS2017+Qt5+Opencv3.4調(diào)用攝像頭拍照并存儲(chǔ)

    本文主要介紹了VS2017+Qt5+Opencv3.4調(diào)用攝像頭拍照并存儲(chǔ),實(shí)現(xiàn)了視頻,拍照,保存這三個(gè)功能。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • OpenCV實(shí)現(xiàn)輪廓檢測與繪制

    OpenCV實(shí)現(xiàn)輪廓檢測與繪制

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)輪廓檢測與繪制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Qt界面美化之自定義qss樣式表的詳細(xì)步驟

    Qt界面美化之自定義qss樣式表的詳細(xì)步驟

    很多人應(yīng)該和我一樣,想做界面才接觸的Qt,結(jié)果就是做不出來華麗的界面,下面這篇文章主要給大家介紹了關(guān)于Qt界面美化之自定義qss樣式表的詳細(xì)步驟,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • Visual Studio Code (vscode) 配置C、C++環(huán)境/編寫運(yùn)行C、C++的教程詳解(主要Windows、簡要Linux)

    Visual Studio Code (vscode) 配置C、C++環(huán)境/編寫運(yùn)行C、C++的教程詳解(主要Windo

    這篇文章主要介紹了Visual Studio Code (vscode) 配置C、C++環(huán)境/編寫運(yùn)行C、C++(主要Windows、簡要Linux),本文通過實(shí)例截圖給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評(píng)論