Java 정적 이니셜 라이저 스레드는 안전합니까? addController(new FooControllerImpl());

정적 코드 블록을 사용하여 레지스트리의 일부 컨트롤러를 초기화하고 있습니다. 내 질문은 따라서이 정적 코드 블록이 클래스가 처음로드 될 때 절대적으로 한 번만 호출된다는 것을 보장 할 수 있습니까? 이 코드 블록이 언제 호출되는지 보장 할 수 없다는 것을 이해합니다. 클래스 로더가 처음로드 할 때 추측합니다. 정적 코드 블록의 클래스에서 동기화 할 수 있다는 것을 알고 있지만 실제로는 이것이 실제로 어떻게됩니까?

간단한 코드 예제는 다음과 같습니다.

class FooRegistry {

    static {
        //this code must only ever be called once 
        addController(new FooControllerImpl());
    }

    private static void addController(IFooController controller) { 
        // ...
    }
}

아니면 내가해야합니까;

class FooRegistry {

    static {
        synchronized(FooRegistry.class) {
            addController(new FooControllerImpl());
        }
    }

    private static void addController(IFooController controller) {
        // ...
    }
}



답변

예, Java 정적 초기화 프로그램은 스레드로부터 안전합니다 (첫 번째 옵션 사용).

그러나 코드가 정확히 한 번만 실행되도록하려면 단일 클래스 로더 만 클래스를로드해야합니다. 정적 초기화는 클래스 로더 당 한 번 수행됩니다.


답변

게으른 초기화에 사용할 수있는 트릭입니다

enum Singleton {
    INSTANCE;
}

또는 Java 5.0 이전

class Singleton {
   static class SingletonHolder {
      static final Singleton INSTANCE = new Singleton();
   }
   public static Singleton instance() {
      return SingletonHolder.INSTANCE;
   }
}

SingletonHolder의 정적 블록은 스레드 안전 방식으로 한 번 실행되므로 다른 잠금이 필요하지 않습니다. singletonHolder 클래스는 instance ()를 호출 할 때만로드됩니다.


답변

일반적인 상황에서는 정적 이니셜 라이저의 모든 것이 해당 클래스를 사용하는 모든 것보다 먼저 발생하므로 일반적으로 동기화가 필요하지 않습니다. 그러나 클래스는 정적 intiailiser가 호출하는 모든 항목에 액세스 할 수 있습니다 (다른 정적 초기자를 호출하는 것을 포함하여).

클래스는로드 된 클래스에 의해로드 될 수 있지만 반드시 즉시 초기화 될 필요는 없습니다. 물론 클래스는 클래스 로더의 여러 인스턴스에 의해로드 될 수 있으며 같은 이름을 가진 여러 클래스가 될 수 있습니다.


답변

예, 일종의

static초기화는 그래서 정의 그것의 스레드 안전에 의해 한 번 호출됩니다 – 당신은 두 개 이상의 호출이 필요할 것 static조차 얻을 스레드 경합 이니셜 라이저.

즉, static이니셜 라이저는 다른 많은 방법으로 혼란스러워합니다. 그들이 부르는 순서는 실제로 없습니다. static이니셜 라이저가 서로 의존하는 두 개의 클래스가 있으면 혼란 스럽습니다 . 클래스를 사용하지만 static초기화 프로그램이 설정 한 것을 사용하지 않으면 클래스 로더가 정적 초기화 프로그램을 호출한다고 보장 할 수 없습니다.

마지막으로 동기화하려는 객체를 명심하십시오. 나는 이것이 실제로 당신이 요구하는 것이 아니라는 것을 알고 있지만, addController()스레드 안전 을 만들어야하는지 질문하지 않아야 합니다.


답변

예, 정적 이니셜 라이저는 한 번만 실행됩니다. 자세한 내용은 이것을 읽으십시오 .


답변

따라서 기본적으로 싱글 톤 인스턴스를 원하기 때문에 어느 정도 구식 방식으로 싱글 톤 객체를 한 번만 초기화해야합니다.


답변