2017-01-28 1 views
0

싱글 톤의 더블 널 확인 구현에서 인스턴스 변수를 휘발성으로 사용하는 것이 무엇인지 알고 싶습니다. 왜냐하면 내 이해에 따라 블록 제공은 암시 적으로 발생하기 전에 동기화됩니다. 두 개의 스레드가 동기화 된 블록을 동시에 액세스 할 수없고 동기화 된 블록에서 빠져 나가는 동안 스레드는 모든 로컬 캐시 된 데이터를 주 메모리에 기록합니다. 많은 검색을했지만 여전히이 구현에 의문의 여지가 있습니다. 올바른 사용법을 설명하십시오.Java에서의 싱글 톤 더블 null 체크 구현에서의 volatile 사용

private volatile Singleton INSTANCE; 
public Singleton get() { 
    if (INSTANCE == null) { 
     synchronized (this) { 
      if (INSTANCE == null) { 
       INSTANCE = new Singleton(); 
      } 
     } 
    } 
    return INSTANCE; 
} 

위의 중복 확인 코드. 내 인스턴스를 휘발성으로 만들지 않으면 무엇이 문제가 될 수 있습니다. 첫 번째 스레드가 동기화 블록에 들어가면 다른 스레드가 해당 블록에 액세스하지 못하기 때문입니다. 그리고 첫 번째 스레드가 그 블록을 떠날 때. 객체가 생성되고 속성 전에 발생하기 때문에 인스턴스의 최신 값이 주 메모리에 기록됩니다. 그렇다면이 시나리오에서 왜 휘발성이 중요한가?

다음은 비슷한 질문의 링크입니다 (Is there any need to add volatile keyword to guarantee thread-safe singleton class in java?). 그러나 대답은 분명하지 않습니다. 내가 JVM 최적화 어떤 종류의 파괴의 원인이 위에서 주어진 시나리오에서 생각하지 않는다 때문에 나의 이해의 동기화 블록을 제공하기 전에 암시 적으로 발생에 따라

+2

우리가 말하는 코드를 보여 주시고, 우리가 정확히 어떤 일이 일어 났는지 보여주세요. 그런 다음 설명 할 수 있습니다. –

+0

(자세한 정보가 없으면 최상의 dup을 선택하기가 어려울 수 있습니다.) –

+0

질문에 넣으십시오. –

답변

0

여기에서 중요한 점은 바이트 코드 레벨의 JVM 내부 구조 때문입니다. 인스턴스가 JVM은 1 + 2는 다른 관점에서 원자 작업으로 실행된다는 점을 보장 volatile 경우

1. INSTANCE = create Singleton object 
2. call constructor of INSTANCE 

: 문

INSTANCE = new Singleton() 

는 바이트 코드 수준에서 그런 사실은 뭔가 스레드, eg 필드에 저장하기 전에 인스턴스를 스택에 저장합니다. 이 아닌 경우volatile 다른 스레드가 이미있을 수 있습니다. 을 참조하십시오. 생성자가 호출되기 전에 Singleton에 대한 참조가 표시됩니다. 따라서 이러한 스레드는 불완전한 객체를 볼 수 있습니다.

0

동기화 블록의 전에 발생합니다. 동기화 된 블록에서 동시에 두 개의 스레드가 동기화 된 블록에 액세스 할 수 없습니다.

단순한 게으른 싱글 톤 구현이있는 경우 올바른 것입니다. 변수에 대한 모든 액세스는 동기화 된 블록을 거칩니다.

private Singleton INSTANCE; 

public static synchronized Singleton getInstance() { 
    if (INSTANCE == null) { 
    INSTANCE = new Singleton(); 
    } 
    return INSTANCE; 
} 

하지만 일단 안전한 이중 검사 지연 구현을 사용하면 모든 코드 경로가 동기화 된 블록을 통과하는 것은 아닙니다. 이 메서드의 두 번째 호출은 synchronized 블록을 입력하지 않고 로컬 필드에서 변수를 읽습니다. INSTANCE은 휘발성이어야합니다.

private volatile Singleton INSTANCE; 

public Singleton get() { 
    if (INSTANCE == null) { 
    synchronized (this) { 
     if (INSTANCE == null) { 
     INSTANCE = new Singleton(); 
     } 
    } 
    } 
    return INSTANCE; 
} 

안전한 게시에 대한 자세한 내용은 this article에서 확인할 수 있습니다.