我正在尝试将一个Java应用程序移植到Scala。Java应用程序的一部分有一个名为AtomicDoubleBuffer
的实现,该实现在引擎盖下使用Atom LongArray
-使用Double.longBitsToDouble(value)
从双缓冲区读取结果,并使用Double.bdoubleToRawLongBits(value)[/code>写入缓冲区。
我一直在网上寻找可以更好的Scala实现,我发现这个代码块
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的解释表明,在一个线程中更新<code>数组
示例中的此实现是正确的,并且使保证之前发生。
因为写入易失性变量使写入线程之前所做的所有事情对第一次读取此易失性变量的所有线程可见。
在这种情况下,易失性的“标记”变量是记忆屏障的点。
在示例代码中:“
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; }
}
"
当您在< code>update中写入数组时,您还会在其后使用< code>marker=0写入volatile变量;,在从数组中进行任何read in apply
操作之前,首先只通过语句< code >标记读取volatile变量;。
这使得对数组的任何写入(甚至由不同的线程执行)对任何读取都可见(发生在保证之前,在这种情况下,在任何update
完成之后,任何执行application
的线程都会看到它)。