簡體   English   中英

在C ++中,獲取/釋放原子訪問與結合圍欄的寬松訪問之間是否有有效的區別?

[英]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);

非寬松的原子訪問確實提供了信號屏障和線程屏障。

在您的代碼中,對於loadstore ,籬笆和原子操作之間的順序應該顛倒,然后類似於獨立操作,但是有區別。

對原子變量的獲取和釋放操作是單向障礙,但方向相反。 也就是說, 存儲/釋放操作可防止在其后(程序源中)的內存操作在其后被重新排序,而加載/獲取操作可防止在其后的內存操作在其之前被重新排序。

// 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_fencestd::atomic_thread_fence相似,不同之處在於它應該在同一線程內運行,因此編譯器不會為線程間同步生成CPU指令。 它基本上充當了僅編譯器的屏障。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM