【问题标题】:What C++11 <atomic> operations/memory orders guarantees freshness? [duplicate]哪些 C++11 <atomic> 操作/内存顺序可以保证新鲜度? [复制]
【发布时间】:2013-01-19 05:01:33
【问题描述】:

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

有了C++11&lt;atomic&gt;规范,有没有新鲜度的保证?不同内存顺序的描述只处理重新排序(据我所知)。

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

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

【问题讨论】:

  • @UmNyobe 在问我之前我没有找到这个问题的原因是它似乎与挥发物有关。答案是重复的,但问题是 imo 不是因为寻找与您提到的“原子和易失性”问题不同的东西的人会发现这个问题。

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


【解决方案1】:

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

线程 1“应该”在“合理的时间内”看到更新的 cancel_work,但是(显然)没有指定确切的合理性。

【讨论】:

    【解决方案2】:

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

    29.3p13 中有一个一般性声明

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

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

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

    【讨论】:

    • 在真正的 CPU 上,存储缓冲区已经尽可能快地将自身刷新到相干缓存。除了有时可能会停止编译时重新排序,直到出现缓慢的情况,seq_cst 不会让您的商店更快地可见。它只是使当前线程停止直到它可见。但是,是的,在一个假设的 CPU 与 C++ 设计用于高效的通常模型完全不同,这是可能的。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2018-02-09
      • 2015-05-30
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      • 2017-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多