加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 给定的代码线程是否安全?

发布时间:2020-12-16 09:51:00 所属栏目:安全 来源:网络整理
导读:@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 解决方法 简答:没有. ?:=不是原子操作,也不
@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的并发队列(可能是最好和最简单的方法)
>如果你想要scala-way,你应该考虑使用actor作为生产者 – 消费者
>您可以设计自己的同步解决方案

UPD

关于@volatile和对不可变集合的操作的一些澄清.
Scala注释@volatile基本上是java的volatile关键字.在这种情况下,它使var aVector的赋值原子并在其他线程中立即可见,但它不会使(读取 – 更新 – 分配操作)序列成为原子或同步.

这个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通过非原子序列的函数调用进行读取,更新和分配.第二个线程可以在中间更新它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读