2016-10-12 3 views
4

Я пытаюсь перенести приложение Java на Scala. Одна часть Java-приложения имеет реализацию под названием AtomicDoubleBuffer, которая использует AtomicLongArray под капотом - используя результат Double.longBitsToDouble(value) для чтения из двойного буфера и Double.doubleToRawLongBits(value) для записи в буфер.Как реализовать массив летучих элементов

Я искал вокруг сети для реализации Scala, которые могли бы быть лучше, и я приземлился на 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 записи в энергонезависимую переменной делает все вещи, сделанные до в поток записи видимого на все темы что первый читать эту летучую переменную.

В этом случае изменчивая переменная «маркер» является точкой барьера памяти.

в вашем примере кода: «

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; } 
} 

»

, когда вы пишете в массив в update вы также записать в энергонезависимую переменную сразу после этого с помощью marker=0;, и перед любым читать в apply из массива вы сначала читаете переменную volatile только с помощью инструкции marker;.

Это делает любые записи в массив (даже выполненные разными потоками) видимыми для любых чтений (происходит до гарантии, в этом случае после завершения любого update, любой поток, выполняющий apply, увидит его).

+0

Хмм не знал об этом - любые указатели помогут. Один вопрос, хотя в этом фрагменте кода, не является компилятором при любой свободе выполнения какой-либо оптимизации, учитывая, что «маркер» инициализируется значением «0» и всегда устанавливается в одно и то же значение. Я не уверен, но это похоже на то, что компилятор может полностью оптимизировать. Или это незаконно для изменчивой переменной? – Michael

+1

Нет, компилятор не имеет права выполнять какую-либо оптимизацию по летучим переменным, которые могут повлиять на одновременное программирование (например, удаление одного из них, поскольку побочный эффект чтения или записи в энергозависимый - это барьер памяти), а порядок выполнения может быть измененный для них во время выполнения, это точно цель изменчивых переменных. –

+0

И для некоторых указателей, я считаю, что это хорошая ссылка: http://stackoverflow.com/questions/30246007/java-memory-model-volatile-variables-and-happens-before –

Смежные вопросы