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

标签 c++ c++11 language-lawyer stdatomic memory-model

是否符合以下代码标准? (或者它是否可以在不使 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();
}

最佳答案

对于获取/释放,是的,这就足够了。相关引述(来自 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.

关于c++ - std::atomic 内存屏障可以用于在线程之间传输非原子数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35254171/

相关文章:

c++ - 有符号/无符号比较

c++ - 使用类模板参数推导创建的临时对象的调用方法

c++ - 如果在 C++ 中没有先前声明的情况下定义自由函数,是否会隐式内联?

c++ - 为什么在新的 IDE 中必须使用命名空间标准,而用 Turbo C++/Borland C++ 编写的程序不需要命名空间标准?

c++ - "const T*"可以匹配指向自由函数的指针吗?

c++ - 多维数组实现

c++ - 将基本类型数组中的内存重用于不同(但仍然是基本)类型数组是否合法

c++ - 为什么Clang和MSVC不喜欢带有多余括号的成员typedef声明?

c++ - 无操作函数模板

c++ - 复制构造函数初始化