我有这段简单的代码。
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=a
中的zzz()
。当我拿出它时似乎没有任何改变。它为什么存在?
答案 0 :(得分:4)
我能想到的唯一原因是编写该代码的人理解只有数组是易失性的而不是其内容,并添加a = a
来强制执行对数组项执行的写操作的可见性。
当我拿出它时似乎没有任何改变。
它仍然可以在您的机器上使用JVM,但这并不意味着它可以在具有不同JVM的另一台机器上运行。从理论上讲,删除a = a;
语句可能会导致永不停止的while循环。
旁注
我原以为Java内存模型(JMM)可以允许JVM忽略该语句,就像忽略synchronized(new Object())
一样。
但似乎是it is not the case*:
您可能已经注意到我确实提供了一种方法,只需使用数组就可以获得上面的易变写:写出自引用。
* Jeremy Manson是JMM的作者之一。