2017-12-11 29 views
0

다음과 같은 클래스와 두 개의 스레드 t1, t2가 있다고 가정 해 보겠습니다.정적 초기화 (클래스 로딩)가 다른 스레드에 의해 완료되기 전에 스레드가 정적 메서드를 입력 할 수 있습니까?

1) T1은 A. 대한 클래스 로딩에 잠금을 획득 A.aSomeMeth()를 실행

2) T2가 B.bSomeMeth 실행 :

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() {} 
    } 

다음은 교착 상태가 발생하기위한 시퀀스 인() B.

대한 클래스 로딩에 잠금을 획득하는

3)의 T1을 B.bMeth (실행할 진행) 및 A.

4)의 T2의 잠금 procee 채 B에 대한 로크를 필요 ds는 A.aMeth()를 실행하고 B에 대한 잠금을 유지하면서 A에 대한 잠금을 요구합니다.

이것은 잠금을 초래합니다. 하지만 내 경우 t2는 실제로 aMeth()을 입력하고 정적 멤버 str에 액세스하는 동안 차단됩니다. 그래서 스레드에 대한 가능한 특정 조건에서 초기화하기 전에 정적 메서드를 입력 할 수 있는지 알고 싶습니다. 내 테스트 실행에서

, T2는 방법 같은 JIT 최적화가 inlineing, 항상 예상대로 A.aMeth()에서 차단, 그래서 그것을 입력 할 수 있습니다 및 str에 차단할 수있는 코너 케이스가있을 수 등

답변

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

답변에 약간의 변화가 있습니다. 한 번에 "한 번에 하나의 스레드"만으로이 프로세스가 여러 번 발생할 수 있다는 인상을 "한 번에"오해 할 수 있습니다. 또한 로딩과 초기화가 서로 다른 두 가지 일뿐 아니라 반드시 같은 스레드에 의해 수행되는 것은 아니기 때문에 "loaded"를 "initialized"로 변경했습니다. 질문은 초기화에 관한 것입니다 (그러나 두 경우 모두 한 번만 발생할 수 있음). – Holger