2013-06-26 45 views
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 

奇怪的是在zzz()a=a。當我把它拿出來似乎沒有改變任何東西。爲什麼在那裏?

+0

它什麼都不做。它可能在那裏添加了一個斷點。 –

+1

分配給volitle將其發佈給其他線程嗎? –

回答

4

我能想到的唯一原因是編寫該代碼的人理解只有陣列是易失性的,而不是其內容,並且添加了a = a以強制執行對陣列項執行的寫入的可見性。

當我把它拿出來似乎沒有改變任何東西。

它仍然在您的機器上與您的JVM一起工作的事實並不意味着它可以在具有不同JVM的另一臺機器上工作。理論上,刪除a = a;語句可能會導致無盡的while循環。


旁註

我本來以爲Java內存模型(JMM)可能允許一個JVM忽略聲明,以同樣的方式,一個synchronized(new Object())可以忽略不計。但是,這種it is not the case*

看來:

您可能已經注意到,我沒有提供讓上面只是陣列揮發性寫的方式:通過寫了一個自我參照

*傑里米曼森是JMM的作者之一。

+0

我正在考慮你的最後一部分,雖然我很好奇有關刪除死代碼的規則,比如這個volatile變量。 –

+0

@JohnVint它似乎並非如此 - 更新。 – assylias

+0

也爲博客鏈接+1。 – dcernahoschi