[英]In C++, is there any effective difference between a acquire/release atomic access and a relaxed access combined with a fence?
具體來說,以下兩者之間是否存在有效的區別?
i = a.load(memory_order_acquire);
要么
a.store(5, memory_order_release);
和
atomic_thread_fence(memory_order_acquire);
i = a.load(memory_order_relaxed);
要么
a.store(5, memory_order_relaxed);
atomic_thread_fence(memory_order_release);
分別?
非寬松原子訪問是否提供信號防護和線程防護?
你需要
atomic_thread_fence(memory_order_release);
a.store(5, memory_order_relaxed);
和
i = a.load(memory_order_relaxed);
atomic_thread_fence(memory_order_acquire);
取代
a.store(5, memory_order_release);
和
i = a.load(memory_order_acquire);
非寬松的原子訪問確實提供了信號屏障和線程屏障。
在您的代碼中,對於load
和store
,籬笆和原子操作之間的順序應該顛倒,然后類似於獨立操作,但是有區別。
對原子變量的獲取和釋放操作是單向障礙,但方向相反。 也就是說, 存儲/釋放操作可防止在其后(程序源中)的內存操作在其后被重新排序,而加載/獲取操作可防止在其后的內存操作在其之前被重新排序。
// thread 1
// shared memory operations A
a.store(5, std::memory_order_release);
x = 42; // regular int
// thread 2
while (a.load(std::memory_order_acquire) != 5);
// shared memory operations B
內存操作A不能向下移動到store/release
下方,而內存操作B不能向上移動到load/acquire
上方。 線程2讀取5時,內存操作A對B可見,並且同步完成。
作為單向屏障,對x
的寫入可以加入甚至在內存操作A之前,但是由於它不是獲取/釋放關系x
一部分,因此線程2無法可靠地對其進行訪問。
用獨立的線程防護和放松的操作來替換原子操作是類似的:
// thread 1
// shared memory operations A
std::atomic_thread_fence(memory_order_release);
a.store(5, std::memory_order_relaxed);
// thread 2
while (a.load(std::memory_order_relaxed) != 5);
std::atomic_thread_fence(memory_order_acquire);
// shared memory operations B
這樣可以達到相同的結果,但重要的區別是兩個圍欄都不是單向障礙。 如果他們這么做,原子店a
可以在發布之前柵欄進行重新排序,並從原子負載a
可以在采集后圍牆被重新排序,這將打破的同步關系。
一般來說:
該標准允許“獲取/發布”防護欄與“獲取/發布”操作混合使用。
非寬松原子訪問是否提供信號防護和線程防護?
我對您要問的問題不太清楚,因為線程防護通常通常用於寬松的原子操作,但是std::thread_signal_fence
與std::atomic_thread_fence
相似,不同之處在於它應該在同一線程內運行,因此編譯器不會為線程間同步生成CPU指令。 它基本上充當了僅編譯器的屏障。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.