有一个全局变量
int sum=0
运行两个线程,代码如下:
for(int i=1;i<=50;i++)
sum=sum+1;
问两个线程都运行完后,sum的取值范围。
本人虽然运行了n遍,结果都是100,但这是个概率事件,只是100的概率很大。为什么还可能出现其他结果?
这是由于线程执行的并发性,第一个线程还没执行完,就被另一个线程打断,即使只有一句,如果不是原子操作,仍然可以被打断。
博客中讨论出了多种结果,一些明显不对外,本人列出一些有说服力的结果,旨在理解多线程并发运行机制。
第一种:50-100
这种结果,考虑了线程之间相互覆盖的结果,最差也就相当于只跑一次但线程的效果,所以最低是50.
第二种:1-100
没有给出理由,但是1有没有可能出现呢?
第三种:2-100
本人比较认同这种结果,2-49之间的值几乎不可能,但是理论上存在,前面也说了,这是概率事件,只是出现的概率极低,下面分析2-49出现的可能。
首先让第一个线程取得sum=0,不执行加1操作;然后让第二个线程循环49次,接着用第一个线程运行到1-50之间的值,然后第二个线程取得这个值,接着第一个线程运行完,第二个线程在这个值的基础上加1,于是可以得到2-51之间的值,这个需要6次配合,条件苛刻,概率极低。
下面重点说下为什么最低是2.
很简单,就考虑最差的情况,如果第一个线程取得sum=0,还没有加1就被另一个线程打断,不管怎样,最后一定会完成这个加1动作,同样,第二个线程也是。所以最低不能低于2.
其实归根到底,问题出现的原因是,sum=sum+1不是原子操作。