易失性示例(在 JLS8/8.3.1.4 易失性字段中)不起作用



http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4

Java 语言规范 8/8.3.1.4 易失性字段

易失性示例

问题:

在易失性示例中,我将 sync 关键字添加到方法two()以避免在方法two()期间执行one()

但我仍然注意到ji大:为什么?

注意:

我使用 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 的观测值,因为方法 1 可能会在方法 2 获取 i 值的时刻和方法二获取 j 值的时刻之间执行多次。

所以 two(( 方法读取 i,然后按照代码中的确切顺序读取 j。但是在读取之间有一堆 one(( 方法调用,给出的结果为 (4998, 5000(

最新更新