2017-02-05 1 views
0

나는 실제로 동시성을 읽고 있는데 오해가있다.
인용 : DCL에 진짜 문제가 동기화없이 공유 객체 참조를 읽는 것은 잘못 오래된 값을 볼 때 최악의 일이 이 일어날 수 있다는 가정이다Double-Check-Locking은 객체 상태를 보장합니까? (실제 동시성)

(이 경우, 널 (null)) ; 이 경우 DCL 관용구가 자물쇠가 잠겨있는 상태에서 을 다시 시도하여이 위험을 보완합니다. 그러나 최악의 경우는 실제로 상당히 입니다. 참조의 현재 값을 볼 수는 있지만 개체의 상태는으로 부실 값입니다. 이는 개체가 이 잘못된 상태이거나 잘못된 상태 인 것으로 나타 났음을 의미합니다.

브라이언 게츠는 DCL은 현재 메모리 모델은 휘발성 사용하여 작동합니다 기록 후 :

public class DoubleCheckLociing{ 

    private static volatile Resource resource; 

    public static Resource getInstance(){ 
     if(resource == null){ 
      synchronized(DoubleCheckLociing.class){ 
       if(resource == null){ 
        resource = new Resource(); 
       } 
      } 
     } 
     return resource; 
    } 
} 

내가 올바른 상태에 대한 문구를 이해한다면 확실하지 않다.

class Resource{ 
    private Date date = new Date();//mutable thread unsafe class 
    private int k = 10; 

    public Date getDate(){ 
     return date; 
    } 

    public int getK(){ 
     return k; 
    } 

} 

내가 getInstance 항상 항상 올바른 반환 correct 자원을 반환 할 것을 보증한다이 있습니까 k (10)와 date :

Resource 클래스는 다음과 같습니다 상상할 수 있습니다?

+0

* 항상 올바른 k (10) 및 date? *를 반환하는 올바른 리소스를 getInstance가 반환한다는 보장이 있습니까? 따라서 Brian Goetz *가 맞는지 여부를 확인하기 만하면됩니까? – CKing

+0

제 이해가 정확한지 확인해야합니다. 나의 이전의 이해는 완전히 다른 것이었다. 나는 공유 참조의 2 읽기 문제를 생각. 첫 번째는 반환 할 수 있습니다! = nul하지만 두 번째는 null 일 수 있습니다 – gstackoverflow

+0

그리고 이것을 확인한 사이트에서 단 하나의 답을 찾지 못했습니까? – CKing

답변

3

volatile을 사용하면 이러한 보증을받을 수 있습니다. volatile이 없으면 그렇지 않습니다.

하나의 스레드가 volatile 변수 resource을 쓸 때 인스턴스 필드 초기화와 같이 전에 작성한 모든 것이 시스템 메모리에 먼저 기록되도록 '메모리 장벽'이 포함됩니다.

다른 스레드가 resource을 읽으면 메모리 배리어가 포함되어 이후에 수행 된 읽기가 시스템 메모리에서 캐시 된 값을 읽지 않도록합니다.

이러한 두 개의 메모리 장벽은 스레드가 초기화 된 resource 변수를 볼 경우 해당 개체에서 제대로 초기화 된 필드도 확인합니다.

0

getInstance가 항상 올바른 k (10) 및 날짜를 ​​반환하는 올바른 리소스를 반환한다는 보장이 있습니까?

예 아니오. @Matt가 지적한 것처럼 필드가 volatile 인 경우 Resource의 모든 필드는 사용자가 인용 한 이중 점검 잠금 예제의 중요한 부분 인 다른 스레드에 의해 액세스 될 때 적절하게 게시됩니다. volatile 메모리 장벽은이를 보장합니다.

그러나 Resource에는 변경할 수있는 최종 필드가 포함되어 있습니다 (설정 메소드가 추가되었거나 나열되지 않은 경우).필드를 final으로 만들면 Resource에 대한 참조가 게시 될 때 final 필드가 게시 될 것이므로 실제로는 volatile을 사용하지 않아도됩니다.

private final Date date = new Date(); 
private final int k = 10; 

당신은 그러나 언급으로 Date도 변경할 수 있기 때문에,이 완전히 당신을 저장하지 않습니다. 코드 (또는 다른 코드)가 date 필드에서 설정 메서드를 호출하지 않는지 확인해야합니다. 그러면 괜찮습니다.

이것은 스레드 프로그램에서 변경 가능성을 추적하는 것이 얼마나 중요한지에 대한 좋은 예입니다.

+0

하지만 객체의 조합을 실행하지 않으면 생성자에서 설정 한 값 (내 경우에는 인라인)을 확인할 수 있습니다. – gstackoverflow

+0

최종 값이 맞으면 예. 그들이 최종적이지 않다면'휘발성 '은 당신에게 그러한 보증을 제공합니다, 예 @gstackoverflow. – Gray