2016-05-09 55 views
2

我正想通過用例中揮發性和我都遇到過以下情況:多線程「不可預知」的行爲

private static boolean stop = false; 
public static void main(String[] args) throws InterruptedException { 
    Thread runner = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      int i = 0; 
      long start = System.currentTimeMillis(); 
      while(!stop){ 
       i++; 
      } 
      System.out.println("I m done after "+(System.currentTimeMillis() - start)); 
     } 
    }); 

    runner.start(); 
    Thread.sleep(2000); 
    stop = true; 
} 

上面的代碼將無限期運行。這是因爲吊起由編譯器完成,以試圖優化代碼。但是,如果我用其他一些陳述替換,例如i ++System.out.println(「Hello」)。 2秒後停止。

爲什麼這種行爲是這樣的?我正在使用jdk1.7.0_51。

注: 我知道我應該申報停止揮發性。但是,我想知道在上述情況下行爲的原因。

+0

從一個跛腳點,增加值比寫到流更容易。 :)。 – Elltz

+0

我能想到的一個原因是i ++被轉換成Java字節碼,它不使用I/O,因爲System.out.println實際上是I/O。這可能會有足夠的時間查看布爾變量中的更改 – shazin

回答

0

標準輸出是跨線程的共享資源。 Java的PrintStream類使用同步塊進行線程安全,並且所有同步塊都是java中的內存障礙,這就是爲什麼stop字段上的更改在循環內部可見的原因。但是,你不應該依賴這個。

例如,看一看的PrintStream.println實現:

public void println(String paramString) 
{ 
    synchronized (this) 
    { 
    print(paramString); 
    newLine(); 
    } 
}