2

我正在尝试更深入地了解轻松的内存排序。根据 CPP 参考,没有同步,但是仍然保证原子性。在这种情况下,原子性是否不需要某种形式的同步,例如,fetch_add()下面如何保证只有一个线程将值从yto更新y+1,特别是如果写入可以乱序对不同线程可见?是否存在与相关的隐式同步fetch_add

memory_order_relaxed 松弛操作:对其他读取或写入没有同步或排序约束,仅保证此操作的原子性(请参阅下面的松弛排序)

#include <thread>
#include <iostream>
#include <atomic>
#include <vector>
#include <cassert>

using namespace std;

static uint64_t incr = 100000000LL;

atomic<uint64_t> x;

void g()
{
   for (long int i = 0; i < incr; ++i)
   {
      x.fetch_add(1, std::memory_order_relaxed);
   }
}

int main()
{
   int Nthreads = 4;
   vector<thread> vec;
   vec.reserve(Nthreads);
   for (auto idx = 0; idx < Nthreads; ++idx)
      vec.push_back(thread(g));
   for(auto &el : vec)
      el.join();
   // Does not trigger
   assert(x.load() == incr * Nthreads);
}
4

1 回答 1

2

“同步”在 C++ 中有一个非常具体的含义。

指跟随。让我们说:

  1. 线程 A 读取/写入内存 X。(不必是原子的)

  2. 线程 A 写入原子变量 Y。(必须是 areleaseseq_cstwrite)

  3. 线程B读取变量Y,看到A之前写入的值。(必须是anacquireseq_cstread)

    此时,操作 (2) 和 (3) 被称为彼此同步。

  4. 线程 B 读取/写入内存 X。(不必是原子的)

    通常这会导致与线程 A 的数据竞争(未定义的行为),但这不是因为同步。

这仅适用于release//操作acquireseq_cst不适用于relaxed操作。这就是报价的意思。

于 2022-03-03T19:48:27.663 回答