http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4
Java语言规范8 / 8.3.1.4易失字段
volatile example
题:
在volatile的示例中,我将同步关键字添加到方法two()
中,以避免在方法one()
中执行two()
。
但是我仍然注意到j
大于i
:为什么?
注意:
我使用Java HotSpot 1.8.0_112。
If you can not noticed j is larger than i, please set testVolatile()/num to a larger number.
我的演示:
public class VolatileDemo {
static volatile int i = 0, j = 0;
static void one() {
i++;
j++;
}
static synchronized void two() {
if (i != j)
System.out.println("i=" + i + " j=" + j);
}
static void testVolatile() {
int num = 5000;
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
public void run() {
one();
}
}).start();
}
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
public void run() {
two();
}
}).start();
}
}
public static void main(String[] args) {
testVolatile();
}
}
我的结果:
i = 4996 j = 4998
i = 4998 j = 5000
i = 4998 j = 5000
....
最佳答案
这是可能的,并在您提到的链接中进行了描述。在该段的末尾。
但是,方法二的任何给定调用都可能会观察到j的值远大于观察到的i的值,因为方法二可能在方法二获取i和i的值之间被执行多次。方法二获取j值的时刻。
因此,two()方法按照代码中的确切顺序依次读取i和j。但是在读取之间有一个one()方法调用,其结果为(4998,5000)