Java并行易失性I++
我有一个全局变量
volatile i = 0;
和两个线程。每个组件执行以下操作:
i++;
System.out.print(i);
我收到以下组合。12、21和22。
我理解为什么我不能得到11(易失性不允许缓存I)和我也理解12和22。
我不明白的是,怎么可能得到21?
获得这种组合的唯一可能方法是,稍后打印的线程必须是第一个将i
从0递增到1,然后缓存i==1
。然后另一个线程将i
从1递增到2,然后打印2。然后第一个线程打印缓存的i==1
。但我认为volatile
不允许缓存。
编辑:在运行代码10,000次之后,我得到了11次。将volatile
添加到i
根本不会更改可能的组合。
markspace是对的:Volatile禁止i
缓存,但i++
不是原子的。这意味着i
在递增期间仍会在寄存器中得到某种程度上的"缓存"。
r1 = i
//if i changes here r1 does not change
r1 = r1 + 1
i = r1
这就是11仍然有可能的原因。21是因为PrintStream未同步(请参阅Karol Dowbecki的答案)
解决方案
不幸的是++
不是原子操作。尽管volatile
不允许缓存,但允许JVM作为单独的操作进行读取、递增和写入。因此,你试图实现的概念是行不通的。您需要使用synchronized
作为其互斥锁,或者使用类似于AtomicInteger
的命令来提供原子增量操作。
相关文章