【发布时间】:2022-01-24 19:03:09
【问题描述】:
在学习多线程编程时,我编写了以下代码。
#include <thread>
#include <iostream>
#include <cassert>
void check() {
int a = 0;
int b = 0;
{
std::jthread t2([&](){
int i = 0;
while (a >= b) {
++i;
}
std::cout << "failed at iteration " << i << "\n"
// I know at this point a and b may have changed
<< a << " >= " << b << "\n";
std::exit(0);
});
std::jthread t1([&](){
while (true) {
++a;
++b;
}
});
}
}
int main() {
check();
}
因为++a 总是发生在++b 之前,所以a 应该总是大于或等于b。
但实验表明,有时b > a。为什么?是什么原因造成的?我该如何执行?
即使我将 int a = 0; 替换为 int a = 1000;,这也让这一切变得更加疯狂。
程序很快退出,因此不会发生 int 溢出。 我没有发现任何指令在汇编中重新排序可能会导致这种情况。
【问题讨论】:
-
上面的代码没有同步,所以存在竞争条件,我们有未定义的行为。修复 UB 后,我们可以尝试对线程进行推理。在此处查看线程和数据竞争 en.cppreference.com/w/cpp/language/memory_model "...如果发生数据竞争,则程序的行为未定义..."
-
您假设
t2线程同时读取两个变量。t2可以将a读入寄存器然后取消调度,t1可以在再次调度t2之前执行循环的100 次迭代,然后将b读入寄存器,从而使b更大。
标签: c++ multithreading