2017-06-12 3 views
1

http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4volatileの例(JLS8/8.3.1.4 volatileフィールドのもの)が動作しませんか?

Java言語仕様8/8.3.1.4揮発性のフィールド

volatile example

質問:

揮発性の例では、私は実行しないようにする方法two()に同期したキーワードを追加方法two()中のone()

でも、私はまだjiより大きいことに気付きました。なぜですか?

注:

私は、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(); 
    } 
} 

マイ結果:

I = 4996 J = 4998

I = 4998 J = 5000

I = 4998 J = 5000

....

+1

両方のメソッドには、同時実行を防ぐためにsynchronizedキーワードを設定する必要があります。 – qwerty

+0

ありがとう、私はこれがアプローチの1つであることを知っています。Javaは、いくつかの目的のためにロックするよりも便利な第2のメカニズム、揮発性フィールドを提供しています。 – Zenna

答えて

2

あなたが言及したリンクに記載されている可能性があります。これは段落の最後です。

ただし、方法2の任意の呼び出しでは、メソッド1がメソッド2のときに何度も実行される可能性があるため、jの値よりもはるかに大きいjの値が観測される可能性がありますiの値とメソッド2がjの値をフェッチする瞬間をフェッチします。

したがって、two()メソッドは、コード内の正確な順序でiとjを読み取ります。 (4998,5000)

+0

ありがとう、私はこれに気づいた。私のデモコードでは、メソッドtwo()にsynchronizedキーワードを追加したので、メソッドone()はtwo()の間に実行すべきではありません。 – Zenna

+0

@Zennaあなたは2つを同期させています*両方* – Eugene

関連する問題