我试图将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
的元素并不能保证其他线程会看到该更新。我错过了什么吗?或者我是否混淆了整个发生过的事情?
答案 0 :(得分:1)
您的示例中的此实现是正确的,并且在保证之前发生。
打击写入易变变量,写入线程 所有线程对所有线程进行之前所做的所有操作 首先阅读此易变变量。
挥发性"标记"变量是这种情况下的记忆障碍点。
在您的示例代码中: "
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;
在此之后写入volatile变量,
在从数组中读取apply
之前,您首先只通过语句marker;
读取volatile变量。
这使得对数组的任何写入(甚至由不同的线程执行)对任何读取都是可见的(在保证之前发生,在这种情况下,在任何update
完成之后,执行apply
的任何线程都会看到它)。