鑒于:
std::atomic<uint64_t> x;
uint64_t f()
{
x.store(20, std::memory_order::memory_order_relaxed);
x.store(10, std::memory_order::memory_order_relaxed);
return x.load(std::memory_order::memory_order_relaxed);
}
有沒有可能為f回傳之外的值10,假設只有一個執行緒寫入x?對于非原子變數,這顯然不是真的,但我不知道放松是否如此放松以至于它會忽略同一執行緒中的資料依賴性?
uj5u.com熱心網友回復:
加載的結果總是 10(假設只有一個執行緒)。即使是松弛的原子變數也比非原子變數“更強”:
- 與非原子變數一樣,所有執行緒必須就對該變數的所有修改發生的單一順序達成一致,
- 與非原子變數一樣,該單一順序與“先后順序”關系一致,并且
- 該實作將保證潛在的并發訪問會以某種方式將自己整理成所有執行緒都同意的某種順序(從而滿足要求 1)。另一方面,在非原子變數的情況下,潛在的并發訪問會導致未定義的行為。
除非伴隨顯式柵欄,否則不能使用寬松的原子變數來使不同的執行緒彼此同步。與適用于原子變數的其他記憶體排序相比,這就是它放松的感覺。
對于語言律師,請參閱 C 20 [intro.races]/10:
在以下情況下,評估A 發生在評估B之前(或等效地,B發生在A之后):
- A在B之前排序,或 [...]
和 [intro.races]/15:
如果操作一個用于修改的原子物件中號的操作之前發生乙修飾中號,然后甲應早于乙中的修改次序中號。[注意:此要求稱為寫-寫一致性。—尾注]
和 [intro.races]/18:
如果副作用X上的原子物件中號的值計算之前發生乙的中號,然后評價乙應采取從其值X或從副作用y下面X中的修飾順序中號。[注意:此要求稱為讀寫一致性。—尾注]
因此,在您的程式中,20 的存盤發生在 10 的存盤之前(因為它在它之前排序)并且 10 的存盤發生在加載之前。寫寫一致性要求保證10的存盤發生在x20的存盤的修改順序之后。當加載發生時,需要從10的存盤中取出它的值,因為10的存盤發生在之前它并且沒有其他修改可以按照 的修改順序跟隨 10 的存盤x。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/337171.html
