![](/img/trans.png)
[英]Are relaxed atomic store reordered themselves before the release? (similar with load /acquire)
[英]C++: Reordering atomic store (release) and load (acquire)
我編寫了以下代碼,它有點像一個編寫器和一個閱讀器的同步隊列。 從不超過1位讀者和1位作家。
作者反復調用maybePublish
,它被設計為無鎖。 相反,讀者使用spinUntilFreshAndFetch
。 它通過原子變量通知它想要下一個非常新鮮的項目。 存儲之后,它會旋轉原子變量,等待編寫器將其設置回0,之后它可以獲取共享對象並將其放入自己的副本中。
class Shared {
public:
void maybePublish(const Item &item) {
if (mItemSync.load(std::memory_order_acquire) == 1) {
mItem = item;
mItemSync.store(0, std::memory_order_release);
}
}
void spinUntilFreshAndFetch(Item *copy) {
mItemSync.store(1, std::memory_order_release); // A
while (mItemSync.load(std::memory_order_acquire) != 0) { // B
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
*copy = mItem;
}
private:
Item mItem;
std::atomic_int32_t mItemSync = 0;
};
我的擔心是關於A行和B行。我在標准中看不到任何不允許交換這些行的內容。 該標准保證發行不會浮動在收購之上,但並不意味着收購不能浮動在發行之上。
另外,我擔心它可能會被優化。 例如,編譯器是否可以假設,在B處, mItemSync
除了1(來自A行) mItemSync
不能是其他任何東西,並將其轉換為無限循環?
根據我看到的教程,如果我使用std::memory_order_seq_cst
而不能重新排序A和B. 我應該這樣做嗎?
謝謝你的建議!
該計划很好。
原子意味着:編譯器不能在單個線程上重新排序它們,保證波動性(因此沒有無限循環)和原子性(操作是不可分割的)。
獲取和釋放語義意味着: 如果獲取操作觀察到釋放操作的副作用,則在發布之前完成任何操作。
如果我們將釋放表示為}
並獲得為{
。 括號內的任何內容都不能按其語義向外移動。 你的兩個線程看起來就像
reader } { { {{ { { R
writer { { {{ { W }
^ ^ ^ ^
1 2 3 4
作者首先反復嘗試發布和獲取,直到讀者發布才會失敗。
作者將在讀者發布后的某個時間獲得。
與此同時,讀者反復嘗試獲取,在作者發布之前也會失敗。
讀者獲得了。
請注意這4個操作必須按此順序進行。 寫入mItem
保證在2
到3
之間,讀取必須在4
之后進行。 結合平鋪這兩個線程仍保留此屬性意味着程序正常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.