命令再配置
逐次プログラムコンパイラは、コンピュータ実行命令をコンパイルした後に形成された命令シーケンスは、一般的に、この命令シーケンスの出力は、決意の結果であろう;各々が決意の実行結果を有していることを確実にします。しかし、通常の状況、プログラムの実行効率を向上させるために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/
マイクロチャンネル公共数: