@volatile var aVector = Vector(1, 2, 3)
thread one
aVector +:= getAnInt()
thread two
aVector match {
case head +: tail =>
doSomethingWith(head)
aVector = tail
case _ =>
}
JVM version: HotSpot 1.8
Scala version: 2.10.5
Short answer: NO.
+:=
is not an atomic operation, as well as deconstruction +:
and assignment.
So you can have two scenarios when everything is going wrong:
var
), first thread reassigns the var
with appended Vector. In this scenario first element of the Vector (that was appended by first thread) will be processed twice.
var
with the value without first element. In this case element that was appended by first thread will be lost.
There are several possible ways how to make this code thread safe:
Some clarifications about @volatile
and operations on immutable collections.
Scala annotation @volatile
is basically java's volatile keyword. In this case it makes assignments of var aVector
atomic and immediately visible in other threads, but it doesn't make sequence of (read - update - assign operations) atomic or synchronized.
This scala code:
@volatile var aVector = Vector(1, 2, 3)
aVector +:= 1
Compiles to this java:
public final class _$$anon$1 {
private volatile Vector<Object> aVector = package$.MODULE$.Vector().apply(Predef$.MODULE$.wrapIntArray(new int[] { 1, 2, 3 }));
private Vector<Object> aVector() {
return (Vector<Object>)this.aVector;
}
private void aVector_$eq(final Vector<Object> x$1) {
this.aVector = x$1;
}
{
this.aVector_$eq(this.aVector().$plus$colon(BoxesRunTime.boxToInteger(1), Vector$.MODULE$.canBuildFrom()));
}
}
As you can see, Vector gets read, updated and assigned back via non-atomic sequence of function calls. Second thread can update it in-between.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With