8

可能重复:
并发:C++11 内存模型中的原子和易失性

有了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而不是重复读取其本地缓存行而不从主内存刷新它?如果不是,那么做出该保证所需的最低要求是多少?

4

3 回答 3

6

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

29.3p13 中有一个一般性声明:

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

但是没有关于什么构成“合理的时间”的规范。

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

于 2013-02-04T13:31:18.810 回答
3

看来这个答案也回答了我的问题。好吧,希望我的问题能帮助谷歌人更好地找到它。

线程 1“应该”cancel_work在“合理的时间内”看到更新,但是(显然)没有具体说明什么是合理的。

于 2013-02-04T13:27:44.247 回答
2

调用一个函数[未被编译器内联]将自动重新加载任何保存不是立即本地变量的寄存器。因此,只要运行 thread1_func() 的处理器基于 刷新或更新了它的缓存内容store,它就会工作。

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

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

于 2013-02-04T13:37:28.313 回答