2014-04-04 8 views
3

:Java - 동기화시 휘발성이 필요합니까? 다음의 간단한 시나리오에서

class A { 
    int x; 
    Object lock; 

    ... 

    public void method(){ 
    synchronized(lock){ 
     // modify/read x and act upon its value 
    } 
    } 
} 

X 필요는 휘발성해야합니까? 나는 동기화가 원 자성을 보장한다는 것을 알고 있지만 가시성에 대해서는 확신하지 못합니다 ... 자물쇠 -> 수정 -> 자물쇠 -> 자물쇠 보장, 두 번째 잠금 후 x 값이 "신선한"것인가?

+0

'x'는 휘발성 일 필요는 없지만'lock'은 온전함을 위해 final이어야합니다. –

+1

물론, 같은 잠금을 유지하면서'x'를 읽어야합니다. –

답변

5

아니요, 동기화 된에 이미 메모리 장벽이 삽입되어 있으므로 모든 스레드는 현재 스레드가 수행하는 업데이트를보고 다른 스레드가 동일한 잠금에서 동기화한다는 사실을 고려합니다.

휘발성은 동기화 된 것처럼 메모리 장벽이 붙어 있습니다. CPU에 따라 하나의 스레드에서 업데이트가 다른 스레드에서 볼 수 있도록하는 저장소 /로드/전체 장벽이 있습니다. 나는 이것이 CPU 캐시 무효화으로 수행된다고 가정합니다.

편집 방금 ​​읽은 것으로부터 저장소 버퍼가 CPU 캐시로 플러시되고 이것이 가시성을 얻는 방법입니다.

+0

JLS에서이 동작을 설명하는 위치는 어디입니까? – jarnbjo

+0

@jarnbjo Java 메모리 모델 섹션. –

+0

@jarnbjo 이것은 Java 메모리 모델과 관련이 있습니다. * 가시성 *은 메모리 장벽으로 해결됩니다. – Eugene

1

간체 대답 : 스레드 A가 필드를 업데이트 한 다음 잠금을 해제하면 스레드 B는 스레드 B가 동일한 잠금을 획득 한 후 업데이트를 보게됩니다.

참고 : "잠금 해제"는 synchronized 블록을 종료한다는 것을 의미하며 "동일한 잠금을 획득합니다"는 동일한 개체를 동기화한다는 의미입니다.

+0

* 스레드 B가 사실이 아닌 동일한 잠금 *을 획득 한 후. 갱신 사항을보기 위해 잠금을 획득 할 필요는 없습니다. 그냥 간단한 다시 읽으면 충분합니다. – Eugene

+0

@Eugene Java 언어 사양에서 "메모리 모델"섹션을 읽고 "발생 이전"관계에주의하십시오. 스레드 A가 필드를 쓰고 뮤텍스를 잠금 해제하면 쓰기가 잠금 해제 전에 발생합니다. 그러나 스레드 B가 같은 잠금에서 동기화하지 않고 동일한 필드를 계속 읽는 경우 "이전에 발생"관계가 없습니다. JVM이 스레드 B가 방법에 상관없이 로컬 캐시 된 오래된 값을 볼 수있게하는 것은 완전히 합법적입니다. 쓰레드 A가 쓴 이후로 많은 실시간이 경과했다. –

+0

올바르게 구현 된 JVM이 할 수있는 일과 특정 일에 JVM이 실제로하는 것과 다른 점을 혼동하지 마십시오. –