亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

并發性:C+11內存模型中的原子和易失性

并發性:C+11內存模型中的原子和易失性

C++
紅糖糍粑 2019-10-21 16:12:10
并發性:C+11內存模型中的原子和易失性在兩個不同內核上并發運行線程之間共享一個全局變量。線程寫入變量并從變量中讀取。對于原子變量,一個線程可以讀取一個陳舊的值嗎?每個核心的緩存中可能有一個共享變量的值,當一個線程在緩存中寫入其副本時,另一個核心上的線程可能從自己的緩存中讀取陳舊的值?;蛘呔幾g器會對其他緩存中的最新值進行強內存排序?c+11標準庫具有std:原子支持。這與易失性關鍵字有何不同?在上述場景中,易失性類型和原子類型的行為會有多大不同?
查看完整描述

3 回答

?
哈士奇WWW

TA貢獻1799條經驗 獲得超6個贊

首先,volatile并不意味著原子訪問。它是為諸如內存映射I/O和信號處理之類的東西而設計的。volatile在一起使用時完全沒有必要std::atomic,除非你的平臺文件另有規定,volatile對線程之間的原子訪問或內存排序沒有影響。

如果有一個在線程之間共享的全局變量,如:

std::atomic<int> ai;

然后,可見性和排序約束取決于用于操作的內存排序參數,以及鎖、線程和對其他原子變量的訪問的同步效果。

在沒有任何附加同步的情況下,如果一個線程將一個值寫入ai然后,沒有任何東西可以保證另一個線程在任何給定的時間段內都會看到該值。該標準規定“在合理的時間內”它應該是可見的,但是任何給定的訪問都可能返回一個陳舊的值。

的默認內存順序。std::memory_order_seq_cst為所有用戶提供一個單一的全局總訂單。std::memory_order_seq_cst所有變量的操作。這并不意味著您不能得到陳舊的值,但它確實意味著您得到的值決定并由您的操作在這個總順序中的位置決定。

如果有兩個共享變量xy,最初為零,并有一個線程將1寫到x另一個寫2到y,讀取這兩個操作的第三個線程可能會看到(0,0)、(1,0)、(0,2)或(1,2),因為操作之間沒有排序約束,因此操作可能以全局順序出現在任何順序。

如果兩個寫入都來自同一個線程,則x=1以前y=2讀取線程讀取y以前x則(0,2)不再是有效的選項,因為y==2意味著先前寫到x是可見的。其他3對(0,0)、(1,0)和(1,2)仍然是可能的,這取決于2對與2寫的交織方式。

如果使用其他內存順序,如std::memory_order_relaxedstd::memory_order_acquire這樣,約束就會進一步放松,單一的全局排序就不再適用了。如果沒有額外的同步,線程甚至不必就兩個存儲的順序來分離變量達成一致。

確保您擁有“最新”值的唯一方法是使用讀-修改-寫入操作,例如exchange()compare_exchange_strong()fetch_add()..讀-修改-寫入操作有一個附加約束,它們總是對“最新”值進行操作,因此ai.fetch_add(1)由一系列線程進行的操作將返回一個沒有重復或空白的值序列。在沒有附加約束的情況下,仍然無法保證哪些線程會看到哪些值。

使用原子操作是一個復雜的主題。我建議您閱讀大量背景材料,并在使用Atomics編寫產品代碼之前檢查已發布的代碼。在大多數情況下,編寫使用鎖的代碼更容易,而且效率也不會明顯降低。



查看完整回答
反對 回復 2019-10-22
?
RISEBY

TA貢獻1856條經驗 獲得超5個贊

以下是這兩件事的基本概要:

1)易失性關鍵字:
告訴編譯器,這個值可以隨時更改,因此它不應該將其緩存在寄存器中。在C中查找舊的“寄存器”關鍵字?!耙资浴被旧鲜恰?”操作符來“注冊”的“+”?,F代編譯器現在做的優化,“寄存器”在默認情況下明確請求,所以你只看到‘易失性’。使用易失性限定符將確保您的處理不會使用陳舊的值,但不會使用更多的值。

2)原子:
原子操作在單個時鐘滴答中修改數據,因此任何其他線程都不可能在更新過程中訪問數據。它們通常僅限于硬件支持的任何單時鐘組裝指令;例如+、-和交換2個指針。請注意,這并沒有說明不同線程將運行原子指令的順序,只是它們永遠不會并行運行。這就是為什么你有那么多額外的選項來強制訂貨。



查看完整回答
反對 回復 2019-10-22
  • 3 回答
  • 0 關注
  • 303 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號