为何两个不同线程递增变量时未出现竞态条件?
竞态条件相关问题解答
1. ++运算符是原子操作吗?
不是。var++在底层会被拆解为三个独立的操作:
- 从内存加载
var的值到CPU寄存器 - 将寄存器中的值加1
- 将新值写回内存
这三个步骤并非原子执行,多个线程同时操作时,很可能出现两个线程同时加载同一个var值,各自完成递增后写回,最终只实现了一次有效递增的情况——这就是你预期的竞态条件。
2. 如何修改程序复现竞态条件?
你的代码没复现竞态,大概率是因为循环次数太少(仅1000次),加上编译器/CPU的优化,导致线程切换的时机很难撞上var++的执行窗口。可以通过以下两种简单修改来提升竞态出现的概率:
修改方案一:大幅增加循环次数
把循环的1000改为100000甚至更大的数值,让线程有更多机会同时操作var:
#include<iostream> #include<thread> using namespace std; int var = 0; void increment() { for(int i=0 ; i<100000; i++) // 增加循环次数 { var++; } } int main() { thread t1(increment); thread t2(increment); t1.join(); t2.join(); cout << "var : " << var << endl; return 0; }
修改方案二:加入微小延迟强制线程切换
在var++前加入短延迟,让当前线程主动放弃CPU,给另一个线程执行的机会,更容易触发竞态:
#include<iostream> #include<thread> #include<chrono> using namespace std; int var = 0; void increment() { for(int i=0 ; i<1000; i++) { this_thread::sleep_for(chrono::nanoseconds(1)); // 加入微小延迟 var++; } } int main() { thread t1(increment); thread t2(increment); t1.join(); t2.join(); cout << "var : " << var << endl; return 0; }
两种修改后,运行程序大概率会得到小于预期值的结果,成功复现竞态条件。
内容的提问来源于stack exchange,提问作者roi_saumon
相关产品推荐
相关产品推荐

