在 C++ 中,acquire/release 原子访问与宽松访问结合栅栏之间是否有任何有效区别?

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);

Non-relaxed 原子访问确实提供信号栅栏和线程栅栏。

在你的代码中,对于loadstore,fence和atomic操作的顺序应该是相反的,然后它类似于standalone操作,但有区别。

对原子变量的获取和释放操作充当 one-way 障碍,但方向相反。 也就是说,store/release 操作会阻止在它之前(在程序源中)的内存操作在它之后重新排序, 而 load/acquire 操作会阻止其后的内存操作在其之前重新排序。

// 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 可见并且同步完成。
作为 one-way 屏障,对 x 的写入可以连接甚至先于内存操作 A,但由于它不是 acquire/release 关系的一部分 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

这实现了相同的结果,但一个重要的区别是两个栅栏都不充当 one-way 障碍; 如果他们这样做了,到 a 的原子存储可以在释放栅栏之前重新排序,并且来自 a 的原子加载可以在获取栅栏之后重新排序,并且 那会破坏同步关系。

总的来说:

  • 独立的发布围栏可以防止前面的操作被后面的(原子)存储重新排序。
  • 一个独立的获取栅栏可以防止后面的操作被前面的(原子)加载重新排序。

标准允许 Acquire/Release 栅栏与 Acquire/Release 操作混合。

Do non-relaxed atomic accesses provide signal fences as well as thread fences?

我不太清楚你在这里问什么,因为线程栅栏通常用于宽松的原子操作, 但是 std::thread_signal_fence 类似于 std::atomic_thread_fence,除了它应该在同一个线程中运行并且 因此,编译器不会为 inter-thread 同步生成 CPU 指令。 它基本上充当 compiler-only 屏障。