请参阅以下从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4507.pdf第12页提供的代码:
using namespace std::experimental::parallel;
std::atomic<int> x = 0;
int a[] = {1,2};
for_each(par, std::begin(a), std::end(a), [&](int n) {
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) { }
});
在此示例中附有注释:
上面的示例取决于迭代的执行顺序,因此未定义(可能会死锁)。
但是我不明白为什么会导致僵局。据我了解,尽管将内存顺序指定为std::memory_order_relaxed
,但这仅与某个线程看到另一个线程所做的某些更改的时间有关,因此最终(在可能无限制的时间之后)该更改应该始终由读取线程注意到。
有人可以解释吗?谢谢!
示例代码可能死锁的原因与的使用无关memory_order_relaxed
。
原子变量的更改将对另一个内核可见,如果不可见(根据标准,它应该变为可见),则它与内存排序无关,后者仅用于指定相对于其他内存操作的排序方式原子操作。
链接引用的文档中给出的示例可能会死锁,因为显然不能保证执行是真正并发的。在更高的草案(N4640)中,该文本进行了修订:
...取决于迭代的执行顺序,并且如果两个迭代均在同一执行线程上依次执行,则不会终止。
这就是全部内容。如果两个迭代都按顺序执行,则第一个迭代将继续旋转一个永不改变的值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句