c++ - 如果中间有线程连接,为什么不能使用宽松的原子操作来同步内存?

标签 c++ multithreading c++11 memory-model stdatomic

我正在观看 Herb Sutter 的演讲:https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

看两个例子(大约 1:15 分),一个对我来说有意义,另一个对我来说没有意义。

第一个例子(有意义):

注意 count 是一个原子整数。

在这里,使用宽松的内存顺序进行加载/存储计数被认为是可以的,因为线程退出发生在从线程上的连接返回之前。这意味着松弛添加发生在松弛加载之前。

子线程:

while (...) {
  if (...) {
    count.fetch_add(1, memory_order_relaxed);
  }
}

主线程:

int main() {
  launch_workers();
  join_workers();
  cout << count.load(memory_order_relaxed);
}

第二个例子(不清楚):

注意 dirtystop 是原子 bool 值。

这里,讲的是dirty上的store和load必须分别使用release和acquire排序,因为dirty是用来发布一些被读取用于清理的数据.

子线程:

while(!stop.load(memory_order_relaxed)) {
  if (...) {
    // publish some data
    dirty.store(true, memory_order_release)
  }
}

主线程:

int main() {
  launch_workers();
  stop = true;
  join_workers();
  if (dirty.load(memory_order_acquire)) {
    // read published data to clean up
  }
}

我的问题是,在第二个示例中,为什么不能在线程退出和从线程的连接返回之间应用相同的“先于发生”关系来同步内存?

我认为它可以在 dirty 的操作上使用宽松的内存顺序的方式是:

[子线程做一些工作,包括发布数据]

[子线程退出] -(发生在之前)-> [从 join_workers() 调用中的子线程加入返回]

[主线程都将 dirty 视为 true 并且可以安全地读取已发布的数据以进行清理]

最佳答案

大约 1 点 17 分 25 秒,他说“现在,因为你碰巧知道我通过加入线程获得了一个发布-获取,我已经在其中注入(inject)了一个发布-获取;这可能已经足够好了并且你可以去放松”。所以他似乎在说,最后,如果以宽松的内存顺序访问 dirty 实际上没问题。

关于c++ - 如果中间有线程连接,为什么不能使用宽松的原子操作来同步内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64381415/

相关文章:

C++,隐式转换/构造函数是如何确定的?

C++ 将 2d 数组(由 uniqe_ptr 引用)合并到 3d 数组中

android - 显示对话框几秒钟

c++ - 为什么 std::unique_ptr 不允许类型推断?

c++ - C++1y 中是否需要公共(public)类内类型定义?

c++ - IWebBrowser2 可以将 cookie 存储在用户指定的文件夹中吗?

C++:通过引用和复制构造函数返回

java - 在定义的时间段内通过 Wifi 发现设备

java - 一个线程中的 Thread.sleep() 使 UI 线程也进入休眠状态

c++ - g++ -std=c++0x 的意外编译问题