문제

"인스턴스 필드의 게으른 초기화를위한 이중 확인 관용구"를 고려하십시오.

// Item 71 in Effective Java copied from 블로 치와의 인터뷰.
private volatile FieldType field;
FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized(this) {
            result = field;
            if (result == null) // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
     return result;
}

안전한 방식으로 필드를 재설정 할 수 있기를 원합니다 (내 경우 데이터베이스에서 다시로드하도록 강요). 재설정 방법을 사용 하여이 작업을 수행 할 수 있다고 가정합니다.

void reset() {
   field = null;
}

이것이 필드를 재설정하는 표준 방법입니까? 안전 해요? 함정이 있습니까? Bloch는 두 번 확인한 Lazy-Loading에 대해 다음과 같은 경고를했기 때문에 묻습니다. "관용구는 매우 빠르지 만 복잡하고 섬세하므로 어떤 식 으로든 수정하려는 유혹을받지 마십시오. 일반적으로 복사하고 붙여 넣는 것입니다. 좋은 생각은 아니지만 여기에 적합합니다. "

미리 감사드립니다. 히말라야의 Playa.

도움이 되었습니까?

해결책

예, 이것은 스레드 안전입니다.

동기화 된 블록은 여러 스레드가 불필요하게 호출되는 것을 방지하는 것입니다. computeFieldValue(). 부터 field 휘발성이 좋으며 액세스가 발생합니다 reset 그리고 getField 모두 잘 정리되어 있습니다.

첫 번째 수표가 널이 아닌 경우 getField 수행; result 반환됩니다.

그렇지 않으면 잠금 장치가 획득되어 필드를 널로 설정할 수있는 다른 스레드를 제외하지만 스레드가 설정할 수 있습니다. field null에. 스레드가 설정된 경우 field 무효로서는 아무것도 바뀌지 않았을 것입니다. 그것이 스레드를 동기화 된 블록에 넣은 조건입니다. 다른 스레드가 현재 스레드 수표 후 이미 잠금을 획득하고 필드를 널 비 값으로 설정 한 경우 두 번째 검사가이를 감지합니다.

다른 팁

나는 이것이 안전해야한다고 생각하지만, 현지 변수에 필드를 저장하고 있기 때문입니다. 이 작업이 완료되면 다른 스레드가 필드의 값을 반쯤 재설정하더라도 로컬 변수 참조가 널로 변경되는 방법이 없습니다.

재설정 방법이 reset() 위에 나열된 방법. 그러나 만약 reset() 메소드는 새로운 객체 (아래와 같이)를 인스턴스화하고, 의도 한 것보다 다른 것을 반환 할 수 없습니까?

void reset() {
    field = new FieldType();
}

나는 그것이 스레드-안전이 당신의 의미에 달려 있다고 생각합니다.

첫 인스턴스가 1 초 후에 사용되는 상황으로 끝날 수 있습니다. 괜찮을 수도 있고 그렇지 않을 수도 있습니다.

Reset () 메소드가 정확하지 않다고 생각합니다. 항목 71을 읽으면 다음을 찾을 수 있습니다.

이 코드는 약간 복잡해 보일 수 있습니다. 특히, 로컬 변수 결과의 필요성은 불분명 할 수 있습니다. 이 변수가하는 일은 필드가만 읽으십시오 이미 초기화 된 보통 사례에서.

게으른 초기화는 그렇게 생각하지 않습니다 필드 변경 될 수 있습니다. 필드 가이 연산자들 사이에서 null로 설정된 경우 :

FieldType result = field;
if (result == null) { // First check (no locking)

getfield () 잘못된 결과를 제공합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top