2017-12-11 18 views
0

以下のクラスと2つのスレッドt1、t2があるとします。静的初期化(クラスローディング)が別のスレッドによって完了する前に、スレッドが静的メソッドを入力できますか?

public class A { 
     static String str = "abc"; 

     static { 
      B.bMeth(); 
     } 

     static void aMeth() { 
      System.out.println("A::meth()"); 
      str = "abc2"; 
     } 

     static void aSomeMeth() {} 
    } 

public class B { 

     static { 
      A.aMeth(); 
     } 

     static void bMmeth() {} 
     static void bSomeMeth() {} 
    } 

後にデッドロックが発生するためのシーケンスである:

1)t1はA.

2のクラスローディングのロックを取得A.aSomeMeth()を実行する)t2がB.bSomeMethを実行します()はB.

3のクラスローディングのロックを取得)B.bMethを(実行するT1進む)及びA.

4のロックを保持しながら、Bのロックを必要とする)のT2 procee dsはA.aMeth()を実行し、Bのロックを保持している間にAのロックを要求する。

これはデッドロックを引き起こす。しかし、私の場合、t2は実際にaMeth()と入力され、静的メンバーstrにアクセスするとブロックされます。だから私はスレッドが特別な状態で初期化する前に静的メソッドに入ることが可能かどうかを知りたい。私のテストランで

、t2は法のようなJITの最適化がinlineing、常に期待通りA.aMeth()でブロックされたので、それはそれを入力することができますし、str上でブロックされて任意のコーナーケースがあるかもしれないなど

答えて

1

いいえ、クラスは1つのスレッドで1回のみ初期化できます。別のスレッドが同じクラスにアクセスすると、初期化が完了するまでブロックされます。

+0

右ので、理想的t2はaMeth'( 'でブロックされなければならない)が、JIT aMeth'()'のための方法のインライン化を行うことができ、Bのように静的ブロックは パブリッククラスB { 静的{ のSystem.outのように見えます.println( "A :: meth()"); A.str = "abc2"; } }、t2は静的インスタンス 'str'にアクセスする行でブロックされます。スレッドスタックトレースを取ると、t2は 'aMeth'()メソッドの中にあることになります。 – Hrishikesh

+0

いいえ、これはいくつかの理由で起こることはありません:クラスがロードされているときに、ロードコードはまだ解釈されています。 JITコードにはクラスローディングの処理が含まれていません。すべての初期化処理がすでに完了しているためです。そうしないと、多くの最適化が妨げられます。また、JITはコードの同じ動作を維持する必要があります(!)。 – loonytune

+0

私は少し答えを言い換えました。 「一度に」は、このプロセスが「一度に」1つのスレッドだけで複数回発生する可能性があるという印象を誤って作成します。さらに、ロードと初期化は2つの異なるものであり、必ずしも同じスレッドによって行われるわけではないので、「ロード済み」を「初期化済み」に変更しました。 – Holger

関連する問題