中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

一文帶你讀懂C++memory_order

發布時間:2020-11-06 17:07:56 來源:億速云 閱讀:822 作者:Leah 欄目:開發技術

一文帶你讀懂C++memory_order?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

看了c++并發編程實戰的內存模型部分后,一直對memory_order不太懂,今天在知乎發現了百度的brpc,恰好有關于原子操作的文檔,感覺解釋的很好。為了加深理解,再次總結一遍。

在多核編程中,我們使用鎖來避免多個線程修改同一個數據時產生的競爭條件。但是,鎖會消耗系統資源,當鎖成為性能瓶頸的時候,就需要使用另一種方法——原子指令。c++11中引入了原子類型atomic。

原子指令 (x均為std::atomic)作用x.load()返回x的值。x.store(n)把x設為n,什么都不返回。x.exchange(n)把x設為n,返回設定之前的值。x.compare_exchange_strong(expected_ref, desired)若x等于expected_ref,則設為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,返回修改之前的值。

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

下面看個例子:

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

線程2在ready為true的時候會訪問p,對線程1來說,如果按照正常的執行順序,那么p先被初始化,然后在將ready賦為true。但對多核的機器而言,情況可能有所變化:

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

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

memory order作用
memory_order_relaxed無fencing作用,cpu和編譯器可以重排指令
memory_order_consume后面依賴此原子變量的訪存指令勿重排至此條指令之前
memory_order_acquire后面訪存指令勿重排至此條指令之前
memory_order_release前面的訪存指令勿排到此條指令之后。當此條指令的結果被同步到其他核的cache中時,保證前面的指令也已經被同步。
memory_order_acq_relacquare + release
memory_order_seq_cstacq_rel + 所有使用seq_cst的指令有嚴格的全序關系

有了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配對,確保線程2在看到ready==true時能看到線程1 release之前所有的訪存操作。

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

關于一文帶你讀懂C++memory_order問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

洛扎县| 平乐县| 阜城县| 韶山市| 广西| 和田县| 应城市| 永春县| 浦东新区| 蒲城县| 泗水县| 嘉义县| 太和县| 开远市| 津南区| 淄博市| 周至县| 观塘区| 尚志市| 龙江县| 安义县| 衡东县| 宁陵县| 韶山市| 内乡县| 资溪县| 兴业县| 安乡县| 金华市| 安泽县| 三台县| 商河县| 延庆县| 名山县| 漠河县| 彭阳县| 鄢陵县| 依兰县| 隆尧县| 云安县| 巴彦淖尔市|