我遇到了这个问题:
给定两个线程和一个全局变量
var
,两个线程运行 相同的代码(C / C ++代码):for(int i=0; i<20; i++) { var++; }
线程末尾的
var
有哪些可能的值 执行?
如果每个线程“正确”增加var
- 我猜最大值将为40.
但最低价值呢?如何实现增量操作并实际完成?
注意:对于增量操作没有任何锁定(任何类型)(当然,正确的方法是锁定它 - 问题是出于教育目的)。
答案 0 :(得分:7)
如果var
不是原子类型,则行为未定义。因此,关于可能的最终值的范围的问题是不适当的。
如果var
是原子类型,那么最终结果就好像线程没有同时运行一样。
答案 1 :(得分:3)
如果你没有做任何锁定,那么var++
不是原子的,即变量的写入和读取可以被另一个线程中断。这意味着两个线程都可以读取相同的var值,并同时增加它。
最坏的情况是两个线程完全&#34;同步&#34;那是在完全相同的时间读取和写入var,因此var
的最小结束值为20。
更新:显然,这些数据竞赛无法保证可能的结果,请参阅下面的Bathsheba答案以及他提到的this article。
更新2 :我很好奇,如果在现实世界中我们会看到低于20的值。测试设置(详情:请参阅this gist)
int var
。使用long
和long long
进行测试,没有任何区别pthread
做了20 {000}次var++
预期结果将在20到000和40&000; 000之间:
| Computer | clang | clang -O3 | gcc | gcc -O0 | gcc -O2 |
|-----------------------------------------------|-------|-----------|-------|---------|---------|
| Linux, ThinkPad, x86_64, Intel I7, 4 cores | 19402 | 20000 | 18760 | 16913 | 20000 |
| Linux, Raspberry 3, ARMv7, 4 cores | 19587 | 20000 | 19569 | 19904 | 20000 |
| OSX, Intel i5, 4 cores | 17609 | 20000 | 17206 | 18049 | 20000 |
| Linux, EC2 t2.2xlarge, Intel Xeon E5, 8 cores | 19707 | 20000 | 19744 | 19881 | 40000 |
看起来很有趣:
gcc -O2
的最小值为40&#39;