2015-01-24 1 views
2

나는이 기사를 읽어 The "Double-Checked Locking is Broken" Declaration, 그것은 말한다게으른 초기화 장면에서 이중 확인 잠금 만 끊어 졌습니까?

두 번 검사 잠금 널리 인용 다중 스레드 환경에서 게으른 초기화를 구현하기위한 효율적인 방법 으로 사용됩니다.

불행하게도, 그것은 ... 자바로 구현 된 플랫폼 독립적 인 방법 에서 안정적으로

그리고이 문서 작동하지 않습니다 Double-checked locking: Clever, but broken를, 그것은 말한다 :

가 DCL 관용구 설계된 게으른 초기화 지원 ...

내 질문은 다음과 같습니다.

  1. 지연 초기화를 시도 할 때 이중 확인 잠금 만 끊었습니까?

  2. 아래 코드와 같은 장면에서도 깨졌습니까? (모든 것은 이미 초기화되어 있습니다)?

코드 :

public String refreshJsapiTicket() throws WxErrorException { 

    if (wxMpConfigStorage.isJsapiTicketExpired()) { 
    synchronized (wxMpConfigStorage) { 
     if (wxMpConfigStorage.isJsapiTicketExpired()) { 
     // ... 
     // update 
     wxMpConfigStorage.setJsapiTicket(jsapiTicket, expiresInSeconds); 
     } 
    } 
    } 

} 

public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { 

    protected volatile String jsapiTicket; 
    protected volatile long jsapiTicketExpiresTime; 

    public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { 
    this.jsapiTicket = jsapiTicket; 
    this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l; 
    } 

} 
+6

전체 기사를 읽어보십시오. JDK5 이후, 올바르게 구현되면 이중 검사 잠금이 작동합니다. (즉, 필드가 검사되고 변이 된 것은 '휘발성'으로 선언됩니다.)하지만 많은 경우에 한 단계 더 나아갈 수 있으며 'AtomicReference'와 친구들 만 사용할 수 있습니다. – biziclop

+0

@biziclop 감사합니다. 또 다른 질문, jdk1.4를 사용하면 DCL이 작동하는지 또는 두 번째 질문의 예제 코드에서 작동하지 않습니까? – chanjarster

+3

'AtomicReference' 관용구는 초기화 코드가 한 번만 실행되는 것을 보장 할 수 없습니다. 게으른 초기화는 필요할 때까지 헤비급 초기화를 지연시키기 때문에 주로 'AtomicReference'의 적용 가능성이 상당히 의심 스럽습니다. 반면, * lazy initialization holder class * idiom은 DCL보다 취약성이 적은 동일한 보증을 제공합니다. –

답변

1

대답 한 당신에게 : 예. Java 5 클래스 로더는 정적 필드에 대해 단일 또는 한 번 초기화를 보장합니다. 당신의 2에 대한 답변 : 코드에서 명확하지 않지만 wxMpConfigStorage.isJsapiTicketExpired() 메소드에서 읽는 내용에 달려 있습니다. 쓰레드 안전하지 않은 것을 읽는 것에 기반하여 결정한다면 예 DCL은 실패 할 수 있습니다. 그러나 귀하의 경우 jsapiTicketExpiresTime은 휘발성이므로 스레드를 읽기에 안전하므로 DCL이 유용합니다.

+0

감사합니다 @ 마크, isJsapiTicketExpired 메서드입니다 : public synchronized void isJsapiTicketExpired() {return System.currentTimeMillis()> jsapiTicketExpiresTime; }. 그리고이 결론을 내릴 권리가 있습니까? DCL이 안전한지 아닌지는 다음에 따라 달라집니다. 1) check 메소드가 안전합니까? 2) 게으른 초기화에서 ** a = 새로운 B() **가 재정렬 될 가능성이 있습니까? – chanjarster

+0

예, 확인은 더티 읽기에서 안전해야합니다. – Mak

관련 문제