原子操作的C++ 11內存排序參數指定排序約束。如果你做一個存儲與std::memory_order_release
,並且從另一個線程的負載讀取第二線程與std::memory_order_acquire
然後隨後的讀操作的值將由前店釋放那名第一個線程看到存儲到任何存儲位置的任何值,或稍後的商店到這些存儲位置中的任何一個。
如果同時存儲和後續的加載是std::memory_order_seq_cst
那麼這兩個線程之間的關係是相同的。你需要更多線程才能看出差異。
例如std::atomic<int>
變量x
和y
,無論最初0
線程1:
x.store(1,std::memory_order_release);
線程2:
y.store(1,std::memory_order_release);
線程3:
int a=x.load(std::memory_order_acquire); // x before y
int b=y.load(std::memory_order_acquire);
線程4:
int c=y.load(std::memory_order_acquire); // y before x
int d=x.load(std::memory_order_acquire);
書面,還有就是x
和y
商店之間沒有任何關係,所以它很可能看到a==1
,b==0
螺紋3,和c==1
和d==0
螺紋4
如果所有存儲器訂單更改爲std::memory_order_seq_cst
,那麼這會強制在商店到x
和y
之間訂購。因此,如果線程3看到a==1
和b==0
那麼這意味着商店x
必須商店y
之前,因此,如果線程4看到c==1
,這意味着商店y
已完成,然後店裏x
也必須完成,所以我們必須有d==1
。
在實踐中,然後使用std::memory_order_seq_cst
到處都將增加額外的開銷,要麼加載或存儲或兩者兼而有之,這取決於你的編譯器和處理器架構。例如用於x86處理器的通用技術是使用XCHG
指令,而不是爲std::memory_order_seq_cst
存儲MOV
指令,以便提供必要的排序保證,而對於std::memory_order_release
純MOV
就足夠了。在內存架構更寬鬆的系統上,開銷可能更大,因爲普通加載和存儲的保證更少。
內存排序是很難的。我在my book中用了幾乎整整一章的篇幅。
這取決於底層硬件必須提供什麼。如果您不知道具體是如何工作的,並且不得不根據這一點進行優化,那麼默認值可能是正確的。在常見的x86系統中,如果有的話,幾乎沒有什麼區別。 – 2013-02-13 19:58:44
@Bo Persson在x86上,gcc在seq_cst存儲後插入完整的MFENCE。當你說「退出內存」時,這會使它顯着變慢 – LWimsey 2017-01-24 00:32:21