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

淺談關(guān)于C++memory_order的理解

 更新時(shí)間:2020年08月27日 09:06:39   作者:ManateeFan  
這篇文章主要介紹了淺談關(guān)于C++memory_order的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

看了c++并發(fā)編程實(shí)戰(zhàn)的內(nèi)存模型部分后,一直對(duì)memory_order不太懂,今天在知乎發(fā)現(xiàn)了百度的brpc,恰好有關(guān)于原子操作的文檔,感覺解釋的很好。為了加深理解,再次總結(jié)一遍。

在多核編程中,我們使用鎖來(lái)避免多個(gè)線程修改同一個(gè)數(shù)據(jù)時(shí)產(chǎn)生的競(jìng)爭(zhēng)條件。但是,鎖會(huì)消耗系統(tǒng)資源,當(dāng)鎖成為性能瓶頸的時(shí)候,就需要使用另一種方法——原子指令。c++11中引入了原子類型atomic

原子指令 (x均為std::atomic) 作用x.load()返回x的值。x.store(n)把x設(shè)為n,什么都不返回。x.exchange(n)把x設(shè)為n,返回設(shè)定之前的值。x.compare_exchange_strong(expected_ref, desired)若x等于expected_ref,則設(shè)為desired,返回成功;否則把最新值寫入expected_ref,返回失敗。x.compare_exchange_weak(expected_ref, desired)相比compare_exchange_strong可能有spurious wakeup。x.fetch_add(n), x.fetch_sub(n)原子地做x += n, x-= n,返回修改之前的值。

但僅靠原子指令實(shí)現(xiàn)不了對(duì)資源的訪問控制。這造成的原因是編譯器和cpu實(shí)施了重排指令,導(dǎo)致讀寫順序會(huì)發(fā)生變化,只要不存在依賴,代碼中后面的指令可能會(huì)被放在前面,從而先執(zhí)行它。cpu這么做是為了盡量塞滿每個(gè)時(shí)鐘周期,在單位時(shí)間內(nèi)盡量執(zhí)行更多的指令,從而提高吞吐率。

下面看個(gè)例子:

// thread 1
// ready was initialized to false
p.init();
ready = true;
// thread 2
if(ready) {
 p.bar();
}

線程2在ready為true的時(shí)候會(huì)訪問p,對(duì)線程1來(lái)說(shuō),如果按照正常的執(zhí)行順序,那么p先被初始化,然后在將ready賦為true。但對(duì)多核的機(jī)器而言,情況可能有所變化:

  • 線程1中的ready = true可能會(huì)被cpu或編譯器重排到p.init()的前面,從而優(yōu)先執(zhí)行ready = true這條指令。在線程2中,p.bar()中的一些代碼可能被重排到if(ready)之前。
  • 即使沒有重排,ready和p的值也會(huì)獨(dú)立地同步到線程2所在核心的cache,線程2仍然可能在看到ready為true時(shí)看到未初始化的p。

為了解決這個(gè)問題,cpu和編譯器提供了memory fence,讓用戶可以聲明訪存指令的可見性關(guān)系,c++11總結(jié)為以下memory order:

memory order 作用
memory_order_relaxed 無(wú)fencing作用,cpu和編譯器可以重排指令
memory_order_consume 后面依賴此原子變量的訪存指令勿重排至此條指令之前
memory_order_acquire 后面訪存指令勿重排至此條指令之前
memory_order_release 前面的訪存指令勿排到此條指令之后。當(dāng)此條指令的結(jié)果被同步到其他核的cache中時(shí),保證前面的指令也已經(jīng)被同步。
memory_order_acq_rel acquare + release
memory_order_seq_cst acq_rel + 所有使用seq_cst的指令有嚴(yán)格的全序關(guān)系

有了memoryorder,我們可以這么改上面的例子:

// Thread1
// ready was initialized to false
p.init();
ready.store(true, std::memory_order_release);
// Thread2
if (ready.load(std::memory_order_acquire)) {
  p.bar();
}

線程2中的acquire和線程1的release配對(duì),確保線程2在看到ready==true時(shí)能看到線程1 release之前所有的訪存操作。

注意,memory fence不等于可見性,即使線程2恰好在線程1在把ready設(shè)置為true后讀取了ready也不意味著它能看到true,因?yàn)橥絚ache是有延時(shí)的。memory fence保證的是可見性的順序:“假如我看到了a的最新值,那么我一定也得看到b的最新值”。

到此這篇關(guān)于淺談關(guān)于C++memory_order的理解的文章就介紹到這了,更多相關(guān)C++ memory order內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的停車場(chǎng)管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的停車場(chǎng)管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的停車場(chǎng)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C/C++中的?Qt?StandardItemModel?數(shù)據(jù)模型應(yīng)用解析

    C/C++中的?Qt?StandardItemModel?數(shù)據(jù)模型應(yīng)用解析

    QStandardItemModel?是標(biāo)準(zhǔn)的以項(xiàng)數(shù)據(jù)為單位的基于M/V模型的一種標(biāo)準(zhǔn)數(shù)據(jù)管理方式,本文給大家介紹C/C++中的?Qt?StandardItemModel?數(shù)據(jù)模型應(yīng)用解析,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • C++實(shí)現(xiàn)班車管理系統(tǒng)課程設(shè)計(jì)

    C++實(shí)現(xiàn)班車管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)班車管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目(圖文教程)

    VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目(圖文教程)

    這篇文章主要介紹了VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • C++實(shí)現(xiàn)哈夫曼樹簡(jiǎn)單創(chuàng)建與遍歷的方法

    C++實(shí)現(xiàn)哈夫曼樹簡(jiǎn)單創(chuàng)建與遍歷的方法

    這篇文章主要介紹了C++實(shí)現(xiàn)哈夫曼樹簡(jiǎn)單創(chuàng)建與遍歷的方法,對(duì)于C++算法的學(xué)習(xí)來(lái)說(shuō)不失為一個(gè)很好的借鑒實(shí)例,需要的朋友可以參考下
    2014-07-07
  • C語(yǔ)言指針詳解

    C語(yǔ)言指針詳解

    這篇文章非常詳細(xì)的講解了C語(yǔ)言中指針的概念,包含多種方法,多種定義,全面的說(shuō)明了C語(yǔ)言的特性
    2021-06-06
  • VC程序設(shè)計(jì)小技巧20例

    VC程序設(shè)計(jì)小技巧20例

    這篇文章主要介紹了VC程序設(shè)計(jì)小技巧20例,需要的朋友可以參考下
    2014-07-07
  • C++中的內(nèi)存分區(qū)介紹

    C++中的內(nèi)存分區(qū)介紹

    這篇文章主要介紹了C++中的內(nèi)存分區(qū)介紹,C++的內(nèi)存劃分為棧區(qū)、堆區(qū)、全局區(qū)/靜態(tài)區(qū)、字符串常量和代碼區(qū),本文分別對(duì)他們一一說(shuō)明,需要的朋友可以參考下
    2015-07-07
  • 你真的懂C++中的namespace用法

    你真的懂C++中的namespace用法

    命名空間(namespace)為防止名字沖突提供了更加可控的機(jī)制,命名空間分割了全局命名空間,其中每個(gè)命名空間是一個(gè)作用域,今天通過(guò)本文給大家分享C++中namespace用法,感興趣的朋友一起看看吧
    2021-06-06

最新評(píng)論