2014-11-25 9 views
1

몇 가지 정적 변수를 지연 초기화하는 인스턴스 메소드를 작성하려고합니다. 내가 초기화하는 개체는 변경할 수 없으며 개체의 참조는 다른 인스턴스 또는 클래스의 정적 메서드에 의해 변경되지 않습니다. 많은 다른 스레드에서 클래스의 여러 인스턴스가있을 수 있지만 초기화 코드를 두 번 이상 실행하지 마십시오. 메서드는 수퍼 클래스의 메서드를 재정의하므로 초기화는 인스턴스 메서드에서 수행해야합니다. 내가 사용하고있는 나의 접근 방식은 다음과 같습니다.다중 스레드 상황에서 정적 변수를 지연 초기화하는 중

private static volatile boolean isPrepared; 
private static volatile Object object1; 
private static volatile Object object2; 
private static volatile Object object3; 

@Override 
void prepare() { 
    synchronized (this.getClass()) { 
     if (isPrepared) { return; } 
     object1 = expensiveCalculation1(); 
     object2 = expensiveCalculation2(); 
     object3 = expensiveCalculation3(); 
     isPrepared = true; 
    } 
} 

나는 초기화가 하나의 동기화 블록에서 발생하기 때문에 인스턴스 이제까지 true 않는 object1, object2object3 모든 null이 아닌 것으로 isPrepared을 관찰하는 것은 불가능하다고 가정입니다. 또한 잠금 장치가 this 일 때 prepare()synchronized으로 단순히 선언하면 작동하지 않는다고 가정합니다. 내 가정이 맞습니까? 또한 함께 초기화 된 것으로 간주 할 때 여러 변수를 volatile이라고 표시하는 것이 좋습니까? 아니면 단일 Immutable 클래스에 함께 묶어야합니까? 당신이 필요로하는 다음 모든volatile 변수없이 동기화이기 때문에 불변의 객체로 모든 게으르게 초기화 상태를 묶기

답변

1

일반적으로 선호하는 방법입니다. 초기화가 진행되는 동안 다른 스레드가 초기화를 시작하면 "in progress"상태를 나타내는 volatile에 센티널 값을 쓰는 등의 방법으로 최소화 할 수 있습니다.

+1

답변 해 주셔서 감사합니다. 나는 변수들을 하나의 휘발성 변수로 묶는 접근법을 사용할 것이라고 생각한다. 그러나 휘발성과 동기화 된 블록의 결합이 언급 한 복제 가능성을 완전히 없애는 가장 간단한 방법이 아닙니까? –

+1

예, 그렇습니다. 휘발성 변수에 값이 있는지 먼저 확인한 다음 필요한 경우 동기화 된 블록을 입력하십시오. –

+0

좋은 지적. var가 이미 있으면 다른 스레드를 기다리는 것을 원하지 않을 것입니다. 휘발성 변수 값을 두 번 확인해야합니다. 한 번 동기화 된 블록이 필요한지 한 번 확인하고 블록의 시작 부분에 한 번 확인해야합니까? 초기 검사가 동기화되지 않았기 때문에 동기화 된 블록을 입력 할 때까지 다른 스레드에서 초기화가 완료되었을 수 있습니다. –