Jou*_*uny 9 c++ multithreading
在学习多线程编程时,我编写了以下代码。
#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();
}
Run Code Online (Sandbox Code Playgroud)
因为++a总是发生在++ba 之前,所以应该总是大于或等于 b。但实验表明,有时b > a。为什么?是什么原因造成的?我该如何执行?
即使当我替换int a = 0;为int a = 1000;这也会让这一切变得更加疯狂。
程序很快退出,因此不会发生 int 溢出。我发现汇编中没有指令重新排序可能导致此问题。
由于 ++a 总是发生在 ++ba 之前,所以 ++ba 应该总是大于或等于 b
仅在其执行线程中。并且仅当执行线程可以观察到这一点时。
C++ 需要某种显式“同步”,以便一个执行线程所做的更改对其他执行线程可见。
++a;
++b;
Run Code Online (Sandbox Code Playgroud)
仅凭这些语句,该执行线程实际上无法“区分”是否首先递增a或b。因此,C++ 允许编译器实现它想要的任何优化或代码重新排序步骤,只要它在执行线程中没有可观察到的影响b,并且如果实际生成的代码首先递增,则不会有任何可观察到的影响。这个执行线程不可能区分出差异。
但是,如果有一些“查看”的中间语句a,那么这将不再成立,并且编译器将需要a在以某种方式使用它之前实际生成递增的代码。
这只是这个执行线程。即使可以观察到此执行线程a中更改的相对b顺序,标准也允许 C++ 编译器以任何顺序实际递增实际变量,只要还有任何其他调整可以实现这一点不可观察到的。但它可以被另一个执行线程观察到。为了防止这种情况,有必要采取显式同步步骤,使用互斥体、条件变量和 C++ 执行线程模型的其他部分。
| 归档时间: |
|
| 查看次数: |
654 次 |
| 最近记录: |