Javaの並行処理(IV)秩序

命令再配置

逐次プログラムコンパイラは、コンピュータ実行命令をコンパイルした後に形成された命令シーケンスは、一般的に、この命令シーケンスの出力は、決意の結果であろう;各々が決意の実行結果を有していることを確実にします。しかし、通常の状況、プログラムの実行効率を向上させるためにCPUとコンパイラの下で、いくつかのケースでは、この最適化は、多くの問題を実行するためのロジックをもたらす、最適化するために特定のルールに従って命令を可能にする、主な理由は、そのコードであります同時実行の場合には、曖昧さが生じ、即ち、異なる実行に論理情報は、異なる結果を得るであろう、との間に論理の特定の配列があります。

コード例:

public class Singleton {

    private static Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (null == singleton) {
            synchronized (Singleton.class) {
                if (null == singleton) {
                    singleton = new Singleton();
                }
            }
        }

        return singleton;
    }
}
复制代码

次のコードの場合:

singleton = new Singleton();
复制代码

我々は、順序が考え:
1メモリのブロック割り当て
メモリ2に初期化シングルトンオブジェクトを
3次に、インスタンス変数Mにアドレスを割り当てます

しかし、実際にはJavaバイトコードを表示しません。

public class com.javashizhan.concurrent.demo.base.Singleton {
  public static com.javashizhan.concurrent.demo.base.Singleton getInstance();
    Code:
       0: aconst_null
       1: getstatic     #2                  // Field singleton:Lcom/javashizhan/concurrent/demo/base/Singleton;
       4: if_acmpne     39
       7: ldc           #3                  // class com/javashizhan/concurrent/demo/base/Singleton
       9: dup
      10: astore_0
      11: monitorenter
      12: aconst_null
      13: getstatic     #2                  // Field singleton:Lcom/javashizhan/concurrent/demo/base/Singleton;
      16: if_acmpne     29
      19: new           #3                  // class com/javashizhan/concurrent/demo/base/Singleton
      22: dup
      23: invokespecial #4                  // Method "<init>":()V
      26: putstatic     #2                  // Field singleton:Lcom/javashizhan/concurrent/demo/base/Singleton;
      29: aload_0
      30: monitorexit
      31: goto          39
      34: astore_1
      35: aload_0
      36: monitorexit
      37: aload_1
      38: athrow
      39: getstatic     #2                  // Field singleton:Lcom/javashizhan/concurrent/demo/base/Singleton;
      42: areturn
    Exception table:
       from    to  target type
          12    31    34   any
          34    37    34   any
}
复制代码

19〜26を参照して、実際の順序は:
1.メモリを割り当て
、変数Mインスタンスに割り当てられたアドレス2.
最後にメモリにMシングルトンオブジェクトを初期化3。

問題の原因順次命令に、前スレッドスイッチ26に実行同時マルチスレッドスレッドAが発生した場合、スレッドBが発見された取得ヌル==シングルトン、シングルトンを確立していないが、今回はシングルトンが終了し、初期化されていない、それはNULLポインタにつながります例外。

二、事前発生ルール

コンパイラは最適化することができますが、特定の最適化するコンパイラを必要とすることは事前発生の規則を遵守するものの、制約付き最適化コンパイラの行動の前に発生します。

1.プログラムシーケンスは、ルール
プログラム順に、前の操作が発生する前に、後続の操作、スレッドで。可変修飾手順の前に次の動作のために表示されなければなりません。

変数規則は、揮発性変数への書き込み2.volatile、事前発生揮発性可変動作の後続の読み取り。

3. Aの送信が事前発生した場合にB、BがCのために、前に発生し、C. Aに事前発生

4.ロック規則
ロックするためのロックを解除するためには、事前発生このロック。

5.スタートプロモータースレッドBは、サブスレッドBは、メインスレッドのスレッドBプロモーターの前に動作を確認することができ、スレッド後にメインスレッドを支配します。

6.スレッドルールは、結合
子スレッドBが完了したとき、(メインスレッドは、方法は、サブスレッドBを呼び出すことによって実現される結合)子供のための完全なスレッドBをメインスレッドを待機さ(join()メソッドは、メインスレッドAを返す)、メインスレッドを見ることができます演算サブスレッド。

7.スレッドは、通常割り込み
、割り込みが発生した場合Thread.interrupted()メソッドによって検出することができる割り込み()メソッドは、最初のイベントの中断スレッドコード検出割り込み発生で発生したスレッドの呼び出しを。

8.エンドルールオブジェクト
がファイナライズ発生前のオブジェクトの初期化完了(実行終了コンストラクタ)の()メソッドが開始されます。

終わり。


サイト: javashizhan.com/


マイクロチャンネル公共数:


おすすめ

転載: juejin.im/post/5d947ea26fb9a04e3f4ef8d1