4

我有这段简单的代码。

class A {
    static volatile String[] a = new String[9];

    public static void main(String[] args) {
        new Thread() {
            public void run() {
                for (int i = 0; i < a.length; i++) {
                    while (a[i] == null);
                    System.out.println(a[i]);
                }
            }
        }.start();

        a[0] = "The";
        zzz();
        a[1] = "quick";
        zzz();
        a[2] = "brown​";
        zzz();
        a[3] = "fox";
        zzz();
        a[4] = "jumped";
        zzz();
        a[5] = "over";
        zzz();
        a[6] = "the";
        zzz();
        a[7] = "lazy";
        zzz();
        a[8] = "cat";
        zzz();
    }

    public static void zzz() {
        try {
            Thread.sleep(300);
        } catch (Exception e) {}
        a=a;
    }
}

它输出我所期望的:

$ javac A.java && java A
The
quick
brown​
fox
jumped
over
the
lazy
cat

奇怪的是a=ain zzz()。当我拿出它时,它似乎没有任何改变。为什么会在那里?

4

1 回答 1

4

我能想到的唯一原因是编写该代码的人明白只有数组是易失的,而不是它的内容,并添加a = a以强制对数组项执行的写入可见。

当我拿出它时,它似乎没有任何改变。

它仍然可以在装有 JVM 的机器上工作的事实并不意味着它可以在具有不同 JVM 的另一台机器上工作。从理论上讲,删除该a = a;语句可能会导致一个永无止境的 while 循环。


边注

我原以为 Java 内存模型 (JMM) 可以允许 JVM 忽略该语句,就像synchronized(new Object())可以忽略 a 一样。

然而,情况似乎并非如此*

您可能已经注意到,我确实提供了一种仅使用数组就可以在上面进行 volatile 写入的方法:通过写出 self-reference

*Jeremy Manson 是 JMM 的作者之一。

于 2013-06-26T18:08:32.233 回答