需要知道在 Scala 未来迭代中分配变量是否正确

Need to know if assigning variable in Scala future iteration is correct

给定以下 Scala 代码:

object TestFutures6 extends App {

  val f0 = Future { 0 }
  val f1 = Future { 1 }
  val f2 = Future { 2 }
  val fx = Seq(f0,f1,f2)

  var x: String = _
  println("x="+x)

  fx.map { 
    seq => seq.map { i =>
        println("i="+i)
        if (x == null) {
           x = "abc"
           println("x="+x)
        }

    }
  }


  Thread.sleep(5000)
}

我需要知道将 "abc" 分配给变量 x 是否符合 运行 条件,因为 seq.map 中的迭代可能 运行平行线。当我 运行 代码时,我只打印了一次 "abc",但我想知道是否有问题。

此外,我需要 运行 在以下上下文中播放此代码

import play.api.libs.concurrent.Execution.Implicits.defaultContext

从技术上讲这里存在潜在的竞争条件,尽管它可能永远不会真正发生。

从本质上讲,您依赖的事实是这两行永远不会 "interleaved" 在不同的线程中:

    if (x == null) {
       x = "abc"

如果两个线程在执行将 x 设置为 abc 之前执行空检查,那么它们都将进入该块。

在这个玩具示例中可能不会发生这种情况,因为您的 future 非常简单并且会立即完成,但这是非常糟糕的做法,不应出现在任何生产代码中。

这当然不是线程安全的,并且通常行为是不确定的。当您 运行 它时,您可能看不到问题,但我们不知道您使用的是什么执行上下文。

一般情况下,线程和有状态不会一起出现。如果您必须具有可变状态,请使用为状态设计的 library/technique(例如演员)。