可以使用std :: atomic内存屏障在线程之间传输非原子数据吗?

Ros*_*ina 9 c++ memory-model language-lawyer c++11

以下代码标准是否合规?(或者它可以在不制造x原子的情况下使其符合要求volatile?)

这与之前的问题类似,但是我想引用C++标准的相关部分.

我担心的是原子store()load()没有为非原子变量(x在下面的例子中)提供足够的编译器障碍来正确释放和获取语义.

我的目标是实现无锁原语,例如队列,可以在线程之间传递指向常规C++数据结构的指针.

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

int x; // regular variable, could be a complex data structure

std::atomic<int> flag { 0 };

void writer_thread() {
    x = 42;
    // release value x to reader thread
    flag.store(1, std::memory_order_release);
}

bool poll() {
    return (flag.load(std::memory_order_acquire) == 1);
}

int main() {
    x = 0;

    std::thread t(writer_thread);

    // "reader thread" ...  
    // sleep-wait is just for the test.
    // production code calls poll() at specific points

    while (!poll())
      std::this_thread::sleep_for(std::chrono::milliseconds(50));

    std::cout << x << std::endl;

    t.join();
}
Run Code Online (Sandbox Code Playgroud)

Yam*_*vic 6

有了获得/释放,是的,这就足够了.相关引号(来自cppreference - 在大多数情况下作为标准):

记忆模型

当表达式的评估写入内存位置而另一个评估读取或修改相同的内存位置时,表达式会发生冲突.具有两个冲突评估的程序具有数据竞争,除非两者之一

  • 两个冲突的评估都是原子操作(参见参考资料std::atomic)
  • 其中一个相互冲突的评估发生在另一个之前(见std::memory_order)

的std :: memory_order

发布 - 获取订购

如果标记了线程A中的原子存储并且标记memory_order_release了来自同一变量的线程B中的原子加载,则从memory_order_acquire线程A的角度来看,在原子存储之前发生的所有存储器写入(非原子和放松原子),在线程B中成为可见的副作用,也就是说,一旦原子加载完成,线程B就可以保证看到线程A写入内存的所有内容.