什么C ++ 11 <atomic>操作/内存命令保证新鲜度?</atomic>

时间:2013-02-04 13:23:32

标签: c++ multithreading concurrency c++11 atomic

  

可能重复:
  Concurrency: Atomic and volatile in C++11 memory model

使用C ++ 11 <atomic>规范,是否有保证新鲜度?不同内存顺序的描述只涉及重新排序(据我所见)。

具体来说,在这种情况下:

#include <atomic>

std::atomic<int> cancel_work(0);

// Thread 1 is executing this function
void thread1_func() {

    ...

    while (cancel_work.load(<some memory order>) == 0) {
        ...do work...
    }
}


// Thread 2 executes this function
void thread2_func() {

    ...

    cancel_work.store(1, <some memory order>);

    ...

}

如果线程1和线程2不共享除cancel_work之外的任何其他数据,在我看来,不需要任何排序保证,并且std::memory_order_relax对于存储和加载都是足够的。但这是否可以保证线程1能够看到cancel_work的更新而不是仅重复读取其本地缓存线而不从主存中刷新它?如果没有,那么提供保证所需的最低要求是什么?

3 个答案:

答案 0 :(得分:5)

没有什么可以保证:一切都与订购有关。即使memory_order_seq_cst只是保证事情发生在一个总的顺序中。从理论上讲,编译器/库/ cpu可以在程序结束时安排cancel_store的每个负载。

29.3p13中有一般性陈述

  

实现应该使原子存储在合理的时间内对原子载荷可见。

但没有说明什么是“合理的时间”。

所以:memory_order_relaxed应该没问题,但memory_order_seq_cst可能在某些平台上运行得更好,因为缓存行可能会更快重新加载。

答案 1 :(得分:3)

似乎this answer也回答了我的问题。好吧,希望我的问题能帮助谷歌更好地找到它。

线程1&#34;应该&#34;在&#34;合理的时间内看到更新的cancel_work&#34;但是,(显然)未指定的是什么是合理的。

答案 2 :(得分:2)

调用函数[未被编译器内联]将自动重新加载任何包含非本地变量的寄存器。因此,只要运行thread1_func()的处理器已根据store刷新或更新其缓存内容,它就会起作用。

memory_order_relax应该确保从任何其他处理器缓存中刷新数据(在未来的某个时间点)[这在x86中是自动的,但不是所有类型的处理器,例如某些ARM处理器需要'代码' -driven flushing'],但不保证在任何其他写入[常规或原子变量]之前发生。

请注意,内存顺序仅影响当前线程/处理器。另一个线程或处理器在存储或加载期间所做的事情完全取决于该线程/处理器。我的意思是,在您的情况下thread1_func()可能能够在其他处理器写入值0之后的某个小时间内读取值1 /线。所有的原子操作保证是它获取OLD值或NEW值,从不介于两者之间[除非你使用memory_order_relax,它不强制在线程内的操作之间加载/存储的任何顺序。但是,无论您使用何种内存顺序,原子都应该保证[假设正确实现]该值最终会更新。在一个放松的情况下,更难分辨。