memory_order_relaxed load vs volatile load

时间:2015-08-05 21:35:18

标签: c++ multithreading atomic volatile memory-fences

atomic_uint的值与memory_order_relaxed一起读取并读取volatile unsigned int的值(假设易失性操作是原子的)之间有什么区别?

具体来说,让我们来定义:

解决方案1 ​​

  1. "作家"线程写入atomic_uint(使用任何内存顺序限定符,从memory_order_relaxed到memory_order_seq_cst)
  2. "读者"线程在同一atomic_uint
  3. 上执行原子轻松读取

    解决方案2

    1. "作家"线程写入volatile unsigned int
    2. "读者"线程读取该值
    3. 按原样,我知道这两种情况都不能保证读者阅读作者所写的价值的能力。我试图理解的是易失性读取与放松原子读取之间的区别。在考虑写后读写一致性时,另一方提供了什么?

      我看到的唯一区别是:

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

      还有其他什么吗?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

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

  • volatile最终用ABI(应用程序二进制接口)来指定,它是一个外部接口;挥发物是与外部世界的接口:对此类对象的访问是可观察到的行为的一部分,永远无法进行优化;
  • 原子是完全根据内部语义来指定的;对象的表示不是规范的一部分; 对此类对象的访问是抽象机的一部分,有时可以被优化或在内部进行推理(由编译器使用C / C ++语义)。