scala – 给定的代码线程是否安全?
@volatile var aVector = Vector(1,2,3) 线程一 aVector +:= getAnInt() 线程二 aVector match { case head +: tail => doSomethingWith(head) aVector = tail case _ => } JVM版本:HotSpot 1.8 Scala版本:2.10.5 解决方法
简答:没有.
?:=不是原子操作,也不是解构:和赋值. 一切都出错,你可以有两个场景: >第一个线程读取Vector,附加一个元素,(此时第二个线程读取Vector,删除元素并重新分配Vector var),第一个线程用附加的Vector重新分配var. 在这种情况下,Vector的第一个元素(由第一个线程附加)将被处理两次. >第二个线程读取Vector并处理第一个元素(第一个线程开始,读取向量,追加元素),第二个线程使用没有第一个元素的值重新分配Vector var. 在这种情况下,第一个线程附加的元素将丢失. 有几种方法可以使这段代码线程安全: >您可以使用java的并发队列(可能是最好和最简单的方法) UPD 关于@volatile和对不可变集合的操作的一些澄清. 这个scala代码: @volatile var aVector = Vector(1,3) aVector +:= 1 编译到这个java: public final class _$$anon$1 { private volatile Vector<Object> aVector = package$.MODULE$.Vector().apply(Predef$.MODULE$.wrapIntArray(new int[] { 1,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())); } } 如您所见,Vector通过非原子序列的函数调用进行读取,更新和分配.第二个线程可以在中间更新它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |