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

Can std::atomic memory barriers be used to transfer non-atomic data between threads?

本文关键字:传输 之间 线程 数据 内存 std      更新时间:2023-10-16

以下代码标准是否兼容?(或者它可以在不使原子或volatile的情况下x兼容吗?

这类似于之前的问题,但是我想引用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();
}

通过获取/释放,是的,这就足够了。相关报价(来自 cpp偏好 - 在大多数情况下与标准一样好(:

内存模型

当表达式的计算写入内存位置,而另一个计算读取或修改相同的内存位置时,表达式被称为冲突。具有两个冲突评估的程序具有数据争用,除非

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

标准::memory_order

发布-获取排序

如果线程 A 中的原子存储被标记为

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