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

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

是否符合以下代码标准? (或者它是否可以在不使 x 成为原子或 volatile 的情况下变得合规?)

这类似于 an earlier question,但是我想引用 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();
}

有了acquire/release,是的,这就够了。相关引述(来自cppreference——在大多数情况下达到标准):

Memory Model

When an evaluation of an expression writes to a memory location and another evaluation reads or modifies the same memory location, the expressions are said to conflict. A program that has two conflicting evaluations has a data race unless either

  • both conflicting evaluations are atomic operations (see std::atomic)
  • one of the conflicting evaluations happens-before another (see std::memory_order)

std::memory_order

Release-Acquire ordering

If an atomic store in thread A is tagged memory_order_release and an atomic load in thread B from the same variable is tagged memory_order_acquire, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B, that is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.