原子写入和读取

Atomic write and read

我想了解以下内容:

  1. 第一个线程写入原子变量,例如std::atomic i。第二个线程是否在下一个加载操作中看到新值?

例如:

std::atomic<uint8_t> i=0;

thr1_func()
{
 i.store(1,std::memory_order_relaxed);//here is first step
}

thr2_func()
{
 while(!i.load(std::memory_order_relaxed);//here is next step
}

'i' 变量在存储操作后的第一次加载操作中会有新值吗?或者 'i' 变量可能在第二次或其他命令执行时具有新值?

提前谢谢你。

Does second thread see the new value on the next load operation?

如果下一个 load 操作发生在 store 之后 该原子变量的修改顺序 那么 load 从中读取值store.

有关完整详细信息,请参阅 std::memory_order

Modification order

All modifications to any particular atomic variable occur in a total order that is specific to this one atomic variable.

...

  1. Write-read coherence: if a side effect (a write) X on an atomic object M happens-before a value computation (a read) B of M, then the evaluation B shall take its value from X or from a side effect Y that follows X in the modification order of M

此外,在 [atomics.order] the standard says that:

Implementations should make atomic stores visible to atomic loads within a reasonable amount of time.

实际上,这意味着编译器发出这些存储和加载指令,然后由硬件传播存储的值并使其对其他 CPU 可见。 x86 CPUs 使用存储缓冲区,以便存储的新值首先进入存储缓冲区,并在离开存储缓冲区后的一些(小)时间对其他 CPUs 可见。在此期间,存储该值的 CPU 可以从存储缓冲区中读回它,但其他 CPU 不能。

更多信息:How do I make memory stores in one thread "promptly" visible in other threads?

这个答案:

如果你需要知道加载是在存储之后发生还是存储还没有发生(即延迟加载直到存储)...你可以引入另一个变量,或者像零一样使用 "invalid value",并且然后 "compare_exchange" 检查这个无效值,这样加载就可以知道存储是否已经发生并且存储可以检查值是否已经加载。