3

std::memory_order::relaxedC++ 标准中滥用 of 的例子之一:

std::atomic<int> x{0};
int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) {
    x.fetch_add(1, std::memory_order::relaxed);
    // spin wait for another iteration to change the value of x
    while (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order
});

然后它说,

上面的例子取决于迭代的执行顺序,如果两个迭代在同一个执行线程上按顺序执行,则不会终止。

问题:

  1. 评论说,“不正确:假定执行顺序”。什么是“假定的执行顺序”?我想念它。

  2. “上面的例子取决于迭代的执行顺序”中的“迭代”指的是什么?这是否意味着while循环中的迭代?或者它是指的迭代std::for_each

  3. 如果 的迭代std::for_each由不同的线程并行执行,那么其中一个迭代/线程不会退出是否仍然正确?因为x.fetch_add(1, std::memory_order::relaxed)是原子的,所以一个线程将产生x1,另一个线程将产生x2,并且两个线程都不可能有 x == 1。不?

4

1 回答 1

5

“不正确:假定执行顺序”。什么是“假定的执行顺序”?

它假设 lambda 的主体由多个线程而不是一个线程执行。该标准宁愿说它可以并行执行。

“上面的例子取决于迭代的执行顺序”中的“迭代”指的是什么?

它可能是指另一个线程执行 lambda。但标准不保证有另一个线程。见execution_policy_tag_t

parallel_policy执行策略类型用作唯一类型以消除并行算法重载的歧义并指示并行算法的执行可以并行化。使用此策略调用的并行算法中元素访问函数的调用(通常指定为 std::execution::par)被允许在调用线程或由库隐式创建的线程中执行以支持并行算法执行。在同一线程中执行的任何此类调用相对于彼此的顺序是不确定的。

于 2019-10-08T14:25:26.863 回答