4

atomic_uint用 memory_order_relaxed 读取 a 的值和读取 a 的值有什么区别volatile unsigned int(假设 volatile 操作是原子的)?

具体来说,让我们定义:

解决方案 1

  1. “writer”线程写入atomic_uint(使用任何内存顺序限定符,从 memory_order_relaxed 到 memory_order_seq_cst)
  2. “阅读器”线程在同一个线程上进行原子轻松读取atomic_uint

解决方案 2

  1. “作家”线程写入volatile unsigned int
  2. “读者”线程读取该值

按原样,我知道这两种情况都不能保证读者能够读取作者写入的值。我想了解的是易失性读取和轻松原子读取之间的区别。在考虑写后读一致性时,一个提供什么而另一个不提供什么?

我看到的唯一区别是:

  • volatile 操作不能在它们之间重新排序,而原子负载可以与其他原子操作重新排序

还有别的吗?

4

2 回答 2

3

不保证易失性读取是原子的。这意味着您可以读取一个从未写入变量的值(也永远不会被程序的任何部分写入)。例如,如果您的应用程序只写入0xAAAAAAAA或写入0xBBBBBBBB变量,则 volatile 读取可能会产生0xAAAABBBB. 或者其他任何东西,因为标准没有指定当易失性读取和写入出现在不同线程中而没有其他同步方式时的行为。

我不知道标准是否说它是 UB 或定义的实现。我只能说有些实现(例如 MSVC 2005)将非同步易失性读/写的行为定义为扩展。

于 2015-08-06T01:24:02.483 回答
2

使用memory_order_relaxed本质上为线程间通信提供了一个表现良好的 volatile 变量:

  • volatile 最终是用 ABI(Application Binary Interface)来指定的,它是一个外部接口;volatiles 是与外部世界的接口:对此类对象的访问是可观察行为的一部分,并且永远无法被优化掉
  • 原子纯粹根据内部语义很好地说明;对象的表示不是规范的一部分;对此类对象的访问是抽象机器的一部分,有时可以被优化掉,或者在内部进行推理(通过编译器,根据 C/C++ 语义)。
于 2018-12-10T02:36:44.243 回答