我有一个全局变量
volatile i = 0;
和两个线程。每个都执行以下操作:
i++;
System.out.print(i);
我收到以下组合。 12、21 和 22。
我理解为什么我没有得到 11(volatile 不允许缓存 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 是因为 PrintStreams 不同步造成的(参见 Karol Dowbecki 的回答)
最佳答案
您的代码不能保证哪个线程会调用 System.out
首先。
由于 volatile
关键字,i
的增量和读取按顺序发生,但打印没有。
关于Java 并行 volatile i++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54791318/