为什么这可能导致僵局
Why this may lead to a deadlock?
请参阅以下从http://www.open-std.org/jtc1/sc22/wg21/wg21/docs/papers/2015/n4507.pdf带来的代码。/p>
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
无关的原因。
对原子变量的更改将对另一个核心可见,如果它不明显(根据标准,IT 应该可见),它与内存订购无关,后者仅用于指定与原子操作相对于原子操作的其他内存操作。
文档中给出的示例链接指的是可以死锁的,因为显然不能保证执行是真正的并发。在后来的草稿(N4640)中,文本已进行了修订:
...取决于迭代的执行顺序,如果两个迭代均在同一执行线程上执行。
这就是全部;如果两个迭代均顺序执行,则第一个不断旋转的值永远不会更改。
线程在等待时正在读取新值,因此在某个时候,他们应该看到他们所做的更改。
不,不是。
放松的内存顺序并不意味着"在此阅读之前,最终可以订购其他线程的内容"。这意味着"在读取此内容之前,没有从其他线程中订购事物"。也就是说,任何其他写作都可能永远不会看到。
因此ub。
现在,在实用系统上,放松的记忆顺序(尤其是对于无锁的原子学)完全有可能使其他线程的修改可见。但是就标准而言,这就是UB。而且,一个过度狂热的编译器确实可以将您的代码编译成硬while(true);
,从不费心从变量中读取,因为它知道它看不到其他线程的变化。
x.fetch_add
使原子量增加,但
std::memory_order_relaxed
不是线程的同步点,因此任何两个线程都可以同时具有1个。因为读取模式 - 写入不同步而开始,因此没有所需的x值。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 为什么会发生堆损坏
- 为什么使用 "this" 指针调用派生成员函数?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么比较运算符如此快速
- 为什么 Serial.println(<char[]>);返回随机字符?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为什么不;名字在地图上是按顺序排列的吗
- 我的字符计数代码计算错误.为什么
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 为什么 std::unique 不调用 std::sort?
- 为什么 boost interprocess_condition notify_one陷入僵局?
- 为什么这可能导致僵局