如何实现volatile元素数组

时间:2016-10-12 12:31:15

标签: java multithreading scala

我试图将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 个答案:

答案 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的任何线程都会看到它)。