Javaマルチスレッド同時プログラミングVolatileキーワード


volatileのキーワードは神秘的なキーワードです。J 2 EEのJAVAプログラマはもっと多いことを知っていますが、AndroidのJAVAプログラマはこのキーワードをよく知らないです。誤ったことを少し理解すれば、多くの人がvolatileを変数のロックとして認識するなど、いくつかの同時エラーが発生しやすくなります。わけではない
volatileの特性:
視認性を備える
volatileで修飾された変数に対するスレッドの視認性を保証します。
この変数iは、volatileによって修正された変数iがあり、他のスレッドに対してiの修正がすぐに見られます。
例えば:

volatile int i = 0;//    1
i++; //    2
ステートメント2の実行が完了すると、iの最新の値はすぐにメインメモリ(共有メモリ)に強制更新され、他のスレッドにiをキャッシュしたスレッドを通知し、他のスレッドのワークメモリ内のiが無効になり、メインメモリに最新の値を再読み込みする必要があります。
秩序性を備える
volatileによって修飾された変数は、最適化されたソートされません。
解決した問題の詳細はJavaマルチスレッドを同時にプログラムし、三つの要素を併発する。の三、秩序性です。
コンパイラがプログラムの最適化のために並べ替えを行う場合、volatile変数の読み操作または書き込み操作に出会うと、その前の操作が全部完了し、結果が後の操作が見えます。そして、その後ろの操作が行われていないことを保証します。
原子性を欠く
volatileは原子性を持っていないので、スレッドが不安定です。
実験:

//        
public class SingletonTest {

  private static volatile SingletonTest mInstance = null;

  private SingletonTest() {}

  public static SingletonTest getInstance() {

    if (mInstance == null) {
      mInstance = new SingletonTest();
      System.out.println("       ");
    }

    return mInstance;
  }
}


//     
public class Test {

  public static void main(String[] var0) {
    for(int i = 0; i < 20; i++){
      ThreadTest test = new ThreadTest();
      test.start();
    }
  }

  static class ThreadTest extends Thread{

    @Override
    public void run() {
      super.run();

      SingletonTest.getInstance();
    }
  }

}
結果:
各運転ごとに複数の「初期化完了」を出力します。
volatileの解釈
以下のこの話は「Java仮想マシンを深く理解する」から抜粋します。
「volatileキーワードとvolatileキーワードが入っていないときに発生したコードを見てみます。volatileキーワードを入れると、一つのlockプレフィックスコマンドが追加されます。」
volatileによって修正された変数を読み書きする時、対応するプログラミングの中でメモリ障壁が多くなります。
このロックはメモリバリアです。
メモリ障壁の役割:
1、並べ替えを最適化する時、その後ろの指令がメモリ障壁の前に並ぶことがないことを保証します。前の命令もメモリ障壁の後ろに並ぶことができません。秩序性
2、強制的に書き込み操作後の結果(直ちに)をメインメモリに更新します。
3、更新結果がメインメモリに到達した場合、他のスレッドキャッシュ内の値が失効したことを通知します。
2と3を合わせると視認性があります。
ここでは、多くの人が困惑しているかもしれません。視認性が保証されている以上、ある変数の値を修正したら、メインメモリに更新され、他のスレッドのキャッシュが無効になります。なぜ原子性が保証されないですか?これも前に入った眠いところです。
引き続きi++で分析してください。この中に含まれている命令:
メインメモリからキャッシュ/コマンド1を読み出します。
演算/コマンド2を行います。
キャッシュからメインメモリにリフレッシュ/コマンド3
メモリ障壁/コマンド4
コマンド4(メモリ障壁)は強力ですが、残念なことに/コマンド1、2、3は原子性を備えていませんので、volatileは原子性を備えていません。スレッドは安全ではないので、ロックの代わりには使えません。
使用シーン
いくつかの単純な状態マークのように:

volatile boolean inited = false;

//    1
init(); //    1
inited = true; //    2

//    2
while(inited){
	work(); //    3
}
1、ステートメント1とステートメント2の実行順序を確保することができます。
2、ステートメント2を実行すると、スレッド2は直ちに最新の修正を取得し、ステートメント3を実行することができます。