memory_order_relaxed 是否尊重同一线程内的数据依赖性?

Does memory_order_relaxed respect data dependencies within the same thread?

鉴于:

std::atomic<uint64_t> x;

uint64_t f()
{
    x.store(20, std::memory_order::memory_order_relaxed);
    x.store(10, std::memory_order::memory_order_relaxed);
    return x.load(std::memory_order::memory_order_relaxed);
}

是否有可能 f 到 return 一个不同于 10 的值,假设只有一个线程写入 x?对于非原子变量,这显然不是真的,但我不知道 relaxed 是否放松到会忽略同一线程中的数据依赖?

加载的结果总是10(假设只有一个线程)。即使是宽松的原子变量也比非原子变量“更强”:

  1. 与非原子变量一样,所有线程必须就对该变量的所有修改发生的单一顺序达成一致,
  2. 与非原子变量一样,该单一顺序与“前序”关系一致,并且
  3. 该实现将保证潜在的并发访问将以某种方式将自己分类为所有线程都同意的某种顺序(从而满足要求 1)。另一方面,在非原子变量的情况下,潜在的并发访问会导致未定义的行为。

一个宽松的原子变量不能用于同步不同的线程彼此,除非伴随着显式的栅栏。与适用于原子变量的其他内存排序相比,这就是它放松的意义。

对于语言律师,请参阅 C++20 [intro.races]/10:

An evaluation A happens before an evaluation B (or, equivalently, B happens after A) if:

  • A is sequenced before B, or [...]

和[intro.races]/15:

If an operation A that modifies an atomic object M happens before an operation B that modifies M, then A shall be earlier than B in the modification order of M. [Note: This requirement is known as write-write coherence. — end note]

和[intro.races]/18:

If a side effect X on an atomic object M happens before a value computation 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. [Note: This requirement is known as write-read coherence. — end note]

因此,在您的程序中,20 的存储发生在 10 的存储之前(因为它在它之前排序)并且 10 的存储发生在加载之前。写写一致性要求保证10的store在x的修改顺序中比20的store晚出现。当加载发生时,要求从10的store取值,因为store of 10 发生在它之前并且没有其他修改可以按照 x.

的修改顺序跟在 store of 10 之后