Michael Michael - 1 month ago 9
Scala Question

How to implement an Array of volatile elements

I'm attempting to port a Java application to Scala. One part of the Java application has an implementation called

AtomicDoubleBuffer
which uses an
AtomicLongArray
under the hood - using the result of
Double.longBitsToDouble(value)
to read from the double buffer and
Double.doubleToRawLongBits(value)
to write to the buffer.

I've been looking around the net for Scala implementation that could be better and I landed on this which says that this code block

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


should give me happens-before guarantees. But I'm a little confused at how possible this is. Why should a volatile marker on one variable determine that a previous non-volatile "operation" succeeds? My interpretation of the JSL 17.4.5 suggests that updating elements of
array
in one thread does not guarantee that other threads will see that update. Am I missing something? Or am I confusing the whole happens-before thing?

Answer

This implementation in your example is correct, and makes the happen before guarantees.

Becuse write to volatile variable makes all things made before by the writing thread visible to all threads that first read this volatile variable.

The volatile "marker" variable is the point of memory barrier in this case.

in your example 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; }
}

"

when you write to the array in update you also write to volatile variable right after that using marker=0;, and before any read in apply from array you first read the volatile variable by just the statement marker;.

This makes any writes to the array (even performed by different threads) visible to any reads (happens before guarantee, in this case after any update is complete, any thread performing apply will see it).