2016-04-23 16 views
0

現在、並行性、特に "volatile"キーワードを勉強しようとしています。すべてカウンター変数揮発性を宣言しJava - 揮発性が期待どおりに機能しない

は変数はすぐにメインメモリに書き戻されますカウンタに書き込みます。また、カウンタのすべての読み取りは、メインメモリから直接読み取られます。カウンタ変数の揮発性の宣言は、その後だけでなく、揮発性変数自体がメインメモリに書き込まれ

スレッドがvolatile変数への書き込み

を、どのように見えるかここです。また、volatile変数に書き込む前にスレッドによって変更された他のすべての変数もメインメモリにフラッシュされます。スレッドがvolatile変数を読み込むと、volatile変数と一緒にメインメモリにフラッシュされた、メインメモリから他のすべての変数も読み込まれます。

出典:tutorials.jenkov.com | Java Concurrency - Java Volatile Keyword私は結論になり

/私は揮発性変数に対して行った変更は、常にすべてのスレッドに表示されることを前提としています。だから、私はそれをテストするコードを作る。

TestClass

package org.personal.test1; 

class TestClass { 
    public static int w = 0; 
    public static int x = 0; 
    public static int y = 0; 
    public static volatile int z = 0; 
    private static final int ITERATIONS = 100000; 


    public static void sooPlus(int indents) { 
     for (int i = 0; i < TestClass.ITERATIONS; i++) { 
      TestClass.w++; 
      TestClass.x++; 
      TestClass.y++; 
      TestClass.z++; 
     } 
    } 

    public static void sooMinus(int indents) { 
     for (int i = 0; i < TestClass.ITERATIONS; i++) { 
      TestClass.w--; 
      TestClass.x--; 
      TestClass.y--; 
      TestClass.z--; 
     } 
    } 


    public static synchronized String getVariableValues() { 
     StringBuilder stringBuilder = new StringBuilder(); 
     stringBuilder.append("("); 
     stringBuilder.append("w : "+TestClass.w+", "); 
     stringBuilder.append("x : "+TestClass.x+", "); 
     stringBuilder.append("y : "+TestClass.y+", "); 
     stringBuilder.append("z : "+TestClass.z+")"); 
     return stringBuilder.toString(); 
    } 

} 

Main Class

package org.personal.test1; 

/** 
* <ol type="I"> 
*  <li> 
*   <a href="http://tutorials.jenkov.com/java-concurrency/volatile.html">jenkov.com - Java Volatile Keyword</a> 
*  </li> 
* </ol> 
*/ 
public class Main { 

    public static void main(String[] args) { 
     Main.call1(); 
    } 

    private static void call1() { 
     Main.test1(); 
    } 

    private static void test1() { 
     Thread thread1 = new Thread("Thread1") { 
      @Override 
      public void run() { 
       TestClass.sooPlus(1); 
      } 
     }; 

     Thread thread2 = new Thread("Thread2") { 
      @Override 
      public void run() { 
       TestClass.sooMinus(4); 
      } 
     }; 

     thread1.start(); 
     thread2.start(); 

     try { 
      thread1.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     try { 
      thread2.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     System.out.println(TestClass.getVariableValues()); 

    } 
} 

私が得る結果は、私が期待していたものではありませんでした。

何私が手にすることは、私が期待してい何

(w : -2314, x : -1692, y : -1416, z : -1656) 

(変わる)

(w : 0, x : 0, y : 0, z : 0) 

または少なくとも

(w : -2314, x : -1692, y : -1416, z : 0) 

質問

  1. 私が予想よりも異なる出力の結果、間違った結論を/何を前提としたのですか?
  2. テスト方法が間違っていましたか?はいの場合は、どうすれば修正できますか?
  3. オプション)推奨するJava並行処理に関する良いチュートリアルはありますか?

ノート

  • 私は同様の質問を読み込もうとしましたが、私は完全に質問者が彼の問題を理解するために行うことを試みていたかを理解することができませんでした。
+1

volatileキーワードは、スレッドセーフな弱い形式を提供します。可視性は保証されますが、原子性や相互排除は保証されません。揮発性フィールドがスレッドセーフではない可能性はありますか?はい、フィールドへの書き込みがアトミックでない場合すべての揮発性フィールドで構成されるクラスがスレッドセーフではない可能性はありますか?はい、フィールドへの書き込みによって無効な状態遷移が発生した場合(同期がないため) – scottb

答えて

3

volatileキーワードは、スレッドセーフな弱いフォームを提供します。 の可視性はですが、のアトミック性または相互排他性は保証されていません。

  • 揮発性フィールドがスレッドセーフではない可能性はありますか?スレッドセーフです。不揮発性への書き込みdoublelongの値はアトミックではありませんが、変数doublelongの変数に書き込みます。

  • すべての揮発性フィールドで構成されるクラスはスレッドセーフではありませんか?はい、フィールドへの書き込みによって無効な状態遷移が発生した場合(同期がないため)

(オプション)をお勧めします するJava並行処理上の任意の良いチュートリアルはありますか?

通常この本の権威的扱いとして推奨される本は、Brian Goetzの「Java Concurrency in Practice」です。それは少し古いです。

+0

-1、申し訳ありません。この回答の多くは正しいものです(特に相互排除*について言及してください)。しかし、揮発性の書き込みはアトミックであることが保証されています(https://docs.oracle.com/javase/specs/を参照)。 jls/se8/html/jls-17.html#jls-17.7)、この回答は(誤った)正反対の主張を正面と中央に置きます。 – ruakh

+0

私は訂正しました。答えは改訂されました。 – scottb

+0

ありがとうございます。 downvote retracted。それでも、OPのサンプルコードの本当に重要な点は、 'TestClass.w - ;'のようなものは、完全に別の書き込みが続き、その結果、必ずしも実際にTestClassを減らさないということです。 w '。 (これは 'int tmp = TestClass.w; tmp--; TestClass.w = tmp;'に相当します。これは 'TestClass.w'に対する他の同時の変更を上書き/上書き/破棄できることを意味します)。 – ruakh

関連する問題