gpt4 book ai didi

scala - 给定的代码线程安全吗?

转载 作者:行者123 更新时间:2023-12-04 23:06:45 26 4
gpt4 key购买 nike

@volatile var aVector = Vector(1, 2, 3)

线程一
aVector +:= getAnInt()

线程二
aVector match {
case head +: tail =>
doSomethingWith(head)
aVector = tail
case _ =>
}

JVM 版本:HotSpot 1.8

斯卡拉版本:2.10.5

最佳答案

简短的回答:不。
+:=不是原子操作,也是解构+:和任务。

因此,当一切都出错时,您可能会遇到两种情况:

  • 第一个线程读取 Vector,添加一个元素,(此时第二个线程读取 Vector,移除元素并重新分配 Vector var),第一个线程重新分配 var带有附加的向量。

  • 在这种情况下,Vector 的第一个元素(由第一个线程附加)将被处理两次。
  • 第二个线程读取 Vector 并处理第一个元素(第一个线程启动、读取向量、追加元素),第二个线程重新分配 Vector var带有没有第一个元素的值。

  • 在这种情况下,第一个线程附加的元素将丢失。

    有几种可能的方法可以使此代码线程安全:
  • 可以使用java的并发队列(可能是最好最简单的方法)
  • 如果你想走 scala-way,你应该考虑使用 actor 作为生产者-消费者
  • 您可以设计自己的同步解决方案

  • 更新

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

    这个Scala代码:
    @volatile var aVector = Vector(1, 2, 3)
    aVector +:= 1

    编译到这个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()));
    }
    }

    如您所见,Vector 通过非原子的函数调用序列被读取、更新和分配回。第二个线程可以在中间更新它。

    关于scala - 给定的代码线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31739808/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com