假设 a 是一个由线程 1 和线程 2 共享的初始值为 0 的全局变量,则线程 1 和线程 2 同时执行下面的代码,最终 a 的结果不可能是()
boolean isOdd = false; for(int i=1;i<=2;++i){ if(i%2==1)isOdd = true; else isOdd = false; a+=i*(isOdd?1:-1); }
首先我们要明确一点的是,只有变量a是共享数据,变量i和isOdd不是共享变量,所以,每个线程对a均做了两次读写操作,分别是 “+1” 和 “-2”。
因为“+=”不是原子操作,在执行时会变成多条指令,所以会出现并发问题。这里可以举个简单的例子,a+=1可以理解成a=a+1。如果线程1读取变量a的值为0,此时线程2抢占了CPU,也读取到变量a的值为0,并进行了+1操作,将a=1写入到变量a中。线程2该操作执行完成后,CPU被线程1抢占,会继续进行后续操作,此时线程1使用原先读取到的变量a的值0进行+1操作,然后将a=1写入到变量a,这里相当于是覆盖了之前线程2写入的变量a的值。从结果上来看,线程1和线程2都执行了+1操作,但a的值却是1,看起来像线程1和线程2同时执行的情况。
理解上面这一情况后,就可以很容易进行判断了:
◆ 线程1执行完再线程2执行,1-2+1-2=-2
◆ 线程1和2同时+1,再-2不同时,1-2-2=-3
◆ 线程1和2不同时+1,同时-2,1+1-2=0
◆ 线程1和2既同时+1又同时-2,1-2=-1
所以,不可能出现结果为1的情况,答案选D。