10

是否符合以下代码标准?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();
}
4

1 回答 1

8

有了获取/发布,是的,这就足够了。相关引用(来自cppreference——在大多数情况下与标准一样好):

记忆模型

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

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

std::memory_order

发布-获取排序

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

于 2016-02-07T13:58:32.040 回答