2017-06-12 39 views
1

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4易變的例子(即在JLS8/8.3.1.4 volatile字段中)不起作用?

Java語言規範8/8.3.1.4揮發性字段

volatile example

問題:

在易失性的例子中,我添加同步關鍵字方法two()避免執行one()方法two()

但我仍然注意到j大於i:爲什麼?

注:

我使用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(); 
    } 
} 

我的結果:

我= 4996 J = 4998

我= 4998 J = 5000

我= 4998Ĵ = 5000

....

+1

兩種方法都必須具有synchronized關鍵字以防止同時執行。 – qwerty

+0

謝謝,我知道,這是其中的一種方法,Java提供了第二種機制,volatile字段,比爲某些目的鎖定更方便,我只想知道volatile的用法。 – Zenna

回答

2

這是可能的,它在你提到的鏈接中有描述。這是在段落的末尾。

然而,有可能的是,方法2的任何給定的調用可能觀察到的j的值遠遠大於爲i觀察到的值,因爲方法1可能在方法2之間執行多次獲取我的值和方法二獲取j的值的時刻。

因此two()方法讀取i,然後按照代碼中的精確順序讀取j。但是有一個()方法調用的cople之間的讀取結果爲(4998,5000)

+0

謝謝,我已經注意到了這一點。所以在我的演示代碼中,我將synchronized關鍵字添加到方法two()中,所以方法one()不應該在two(); – Zenna

+0

@Zenna你有兩個同步他們*兩個* – Eugene