[英]Mixing Relaxed and Release-Acquire Memory Orders
考慮std::atomic<int> x(0)
。 如果我理解正確, std::memory_order_relaxed
僅保證操作以原子方式發生,但不提供同步保證。 因此x.fetch_add(1, std::memory_order_relaxed)
來自 2 個線程的x.fetch_add(1, std::memory_order_relaxed)
1000 次將始終具有 2000 的最終結果。 但是,這些調用中的任何一個的返回值都不能保證反映真實的當前值(例如,第 2000 次增量可能返回 1700 作為前一個值)。
但是 - 這就是我的困惑 - 鑒於這些增量是並行發生的, x.load(std::memory_order_acquire)
返回什么? 還是x.fetch_add(1, std::memory_order_acq_rel)
? 這些是否返回真實的當前值,或者它們是否具有由於寬松的增量而導致的寬松排序所具有的過時答案的相同問題?
據我所知,該標准僅保證釋放到獲取(在同一變量上)同步並因此給出真實的當前值。 那么如何輕松混合典型的獲取-釋放語義呢?
例如,我聽說std::shared_ptr
的引用計數以寬松的順序遞增並以 acq_rel 的順序遞減,因為它需要確保它具有真值以便只刪除一次對象。 因此,我很想認為他們會給出真實的當前值,但我似乎找不到任何標准來支持它。
ISO C++ 保證對每個原子對象分別存在一個修改順序。
隨着seq_cst還有的保證是一個全球性的秩序,所有線程能夠同意a
之前,改變b
或東西。 但是對於單個對象,即使放寬了一些操作,也保證存在修改順序。
您從輕松的fetch_add
返回值定義/記錄修改順序是什么。 根據定義,第 2000 次增量返回2000
,這就是您知道它是第 2000 次的方式。
據我所知,該標准僅保證釋放到獲取(在同一變量上)同步並因此給出真實的當前值。
只有當您關心讀取其他值時才需要同步,例如,一個線程存儲到非原子數組,然后執行像data_ready = 1;
這樣的釋放存儲data_ready = 1;
. 為了讓讀者安全地從數組中讀取數據,他們需要在獲取加載時看到data_ready != 0
,這意味着他們還可以看到執行釋放存儲的線程中所有早期分配的效果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.