문제

Java에서 코드 블록에서 동기화를 수행하는 몇 가지 예에서는 해당 변수가 원래 휘발성을 선언하는 동안 일부 변수를 변경하는 것입니다. 싱글 톤 클래스의 예에서 휘발성으로 고유 한 인스턴스를 선언 한 것으로 보았습니다.해당 인스턴스를 초기화하는 블록을 동기화하십시오 ... 내 질문은 우리가 그것에 동기화하는 동안 휘발성을 선언하는 이유이기 때문에 왜 우리가 둘 다 할 필요가 있는가 ??그 중 하나가 다른 것에 충분하지 않은 것은 아니야 ??

public class someClass {
volatile static uniqueInstance = null;

public static someClass getInstance() {
        if(uniqueInstance == null) {
            synchronized(someClass.class) {
                if(uniqueInstance == null) {
                    uniqueInstance = new someClass();
                }
            }
        }
        return uniqueInstance;
    }
.

미리 감사드립니다.

도움이 되었습니까?

해결책

첫 번째 점검이 동기화 된 블록 내에 있지 않은 경우이 경우에 동기화가 충분합니다.휘발성만으로는 원자 적으로 하나 이상의 작업을 수행해야하기 때문에 충분하지 않습니다.그러나 조심하십시오!여기에있는 것은 소위 이중 검사 잠금입니다 - 불행히도 는 안정적으로 작동하지 않습니다 .나는 이것이 Java 1.6 이후로 변경되었지만 여전히이 종류의 코드가 위험 할 수 있습니다.

편집 : 변수가 휘발성 인 경우이 코드는 JDK 5 (이전에 쓴 것처럼 6이 아님) 이후 올바르게 작동하지만 JDK 1.4 또는 이전에 예상대로 작동하지 않습니다.

다른 팁

이중 검사 된 잠금을 사용합니다. if(uniqueInstance == null)가 동기화 된 부분 내에 있지 않습니다.

uniqueInstance가 휘발성이 아닌 경우, 부분적으로 구성된 부분은 synchronized 블록에서 실행되는 스레드 이외의 다른 부분이 보이지 않는 부분적으로 구성된 오브젝트로 "초기화"될 수 있습니다.휘발성은이 경우이 경우 모두 또는 아무것도 작동하지 않습니다.

동기화 된 블록이없는 경우 2 개의 스레드가 동시에이 시점으로 가면 끝낼 수 있습니다.

if(uniqueInstance == null) {
      uniqueInstance = new someClass(); <---- here
.

및 목적을 패배하는 2 개의 SOMECLASS 객체를 생성합니다.

엄밀히 말하면, 당신은 휘발성이 필요하지 않으며, 방법은

public static someClass getInstance() {
    synchronized(FullDictionary.class) {
         if(uniqueInstance == null) {
             uniqueInstance = new someClass();
          }
         return uniqueInstance;
    }
}
.

그러나 getInstance ()를 수행하는 모든 스레드의 동기화 및 직렬화를 증가시킵니다.

이 게시물 아이디어를 설명합니다휘발성 뒤에.

그것은 또한 제자 작업, Java Concurrency 실습 .

동시성은 공유 상태의 보호뿐만 아니라 스레드 간의 상태의 가시성을 포함 할뿐만 아니라 휘발성이 들어오는 곳입니다. (이 더 큰 계약은 Java 메모리 모델 .)

동기화 된 블록을 사용하지 않고 동기화 할 수 있습니다. 그것은 휘발성 변수를 사용하는 것이 필요하지 않습니다 ... 휘발성은 주 메모리에서 한 변수를 업데이트합니다 동기화 된 업데이트 메인 메모리에서 액세스 한 모든 공유 변수를 업데이트하십시오. 따라서 귀하의 요구 사항에 따라 사용할 수 있습니다 ..

여기에 두 센트

frist이 코드의 직관에 대한 간략한 설명

if(uniqueInstance == null) {
        synchronized(someClass.class) {
            if(uniqueInstance == null) {
                uniqueInstance = new someClass();
            }
        }
    }
.

uniqueInstance== NULL의 두 번 검사하는 이유는 상대적으로 느린 동기화 된 블록을 호출하는 오버 헤드를 줄이는 것입니다.소위 이중 체크 잠금이라고합니다.

두 번째로 동기화 된 이유는 이해하기 쉽고 동기화 된 블록 원자 내부에서 두 작업을 만듭니다.

마지막 휘발성 수정자는 모든 스레드가 동일한 복사본을 볼 수 있도록 모든 스레드가 동일한 복사본을 보지 않도록 yournicled 블록 외부의 첫 번째 검사가 "동기화 된"인 방식으로 uniqueInstance 값을 볼 수 있습니다. 동기화 된 블록으로휘발성 수정자가없는 스레드는 uniqueInstance에 값을 할당 할 수 있지만 다른 스레드는 첫 번째 검사에서 볼 수 없습니다.(두 번째 수표가 볼 수 있지만)

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