2016-10-12 2 views
4

Java 응용 프로그램을 스칼라로 이식하려고합니다. Java 응용 프로그램의 한 부분은 이라는 구현을 가지고 있는데, AtomicLongArray을 사용합니다. 이중 버퍼에서 Double.longBitsToDouble(value)의 결과를 사용하고 버퍼에 쓸 때는 Double.doubleToRawLongBits(value)의 결과를 사용합니다. 내가 더 잘 될 수 스칼라 구현을위한 그물 주위에 찾아 봤는데 내가 this에 착륙휘발성 요소의 배열을 구현하는 방법

하는이 코드 블록

class VolatileDoubleArray(val length : Int){ 
    val array = new Array[Double](length); 
    @volatile var marker = 0; 
    def apply(i : Int) = {marker; array(i); } 
    def update(i : Int, x : Double) { array(i) = x; marker = 0; } 
} 

날 발생-전에 보증을 제공해야한다고 말한다. 그러나 나는 이것이 가능한 방법에 조금 혼란스러워합니다. 왜 하나의 변수에있는 휘발성 마커는 이전의 비 휘발성 "연산"이 성공했는지를 결정해야합니까? JSL 17.4.5을 해석하면 한 스레드에서 array의 요소를 업데이트한다고해서 다른 스레드가 해당 업데이트를 볼 수 있다고 보장 할 수는 없습니다. 내가 놓친 게 있니? 아니면 모든 일이 발생하기 전에 혼란 스럽습니까?

답변

1

이 구현은 올바른 것이며 보장 전에 이 발생합니다. 휘발성 변수

Becuse 쓰기 처음이 휘발성 변수을 읽어 모든 스레드 에 볼 수 쓰기 스레드에 의해 전에 만든 모든 것을한다.

휘발성 "마커"변수는이 경우 메모리 장벽의 포인트입니다. 귀하의 예제 코드에서

: 당신이 update의 배열에 쓸 때 는 "

class VolatileDoubleArray(val length : Int){ 
    val array = new Array[Double](length); 
    @volatile var marker = 0; 
    def apply(i : Int) = {marker; array(i); } 
    def update(i : Int, x : Double) { array(i) = x; marker = 0; } 
} 

는"

당신은 또한 사용 marker=0;, 후 apply의 모든 읽기 전에 휘발성 변수 오른쪽으로 쓰기 배열에서 휘발성 변수를 읽으려면 문구 marker; 만 있으면됩니다.

이는 읽기 볼 배열 (심지어 다른 스레드에 의해 수행) 모든 쓰기를합니다 (모든 update이 완료된 후, apply을 수행하는 모든 스레드가 표시됩니다,이 경우에는 보증하기 전에 발생).

+0

흠은 그 사실을 인식하지 못했습니다. 모든 포인터가 도움이 될 것입니다. 그러나이 코드 스 니펫에서 한 가지 질문은 'marker'가 값 '0'으로 초기화되고 항상 같은 값으로 설정된 경우 최적화를 수행 할 자유가없는 컴파일러가 아니라는 것입니다. 확실하지는 않지만 컴파일러가 완전히 최적화 할 수있는 것처럼 보입니다. 아니면 휘발성 변수에서 불법입니까? – Michael

+1

아니요, 컴파일러는 동시 프로그래밍에 영향을 줄 수있는 휘발성 변수에 대한 최적화를 수행 할 자유가 없습니다 (휘발성 변수에 대한 읽기 또는 쓰기의 부작용으로 인해 메모리 장벽이 만들어지기 때문에 컴파일러를 제거하는 등의 일도 없습니다). 런타임에 변경되었으므로 그 것이 휘발성 변수의 목적입니다. –

+0

그리고 몇 가지 포인터에 대해, 나는 이것이 좋은 참고 : http://stackoverflow.com/questions/30246007/java-memory-model-volatile-variables-and-happens-before –

관련 문제