Scala:为什么在新线程中使用变量会导致死锁?[duplicate]

dkqlctbz  于 2022-11-23  发布在  Scala
关注(0)|答案(1)|浏览(130)

此问题在此处已有答案

Akka Streams with Scala 3: mapAsync fails(1个答案)
6天前关闭。
假设我有一段代码,它启动了两个线程,每个线程打印它的工作和工作所需的参数:

object ThreadingDeadlock extends App {
  val jobs = List("foo", "bar")
  val parameter = "Param"

  val threads = jobs
    .map(job => {
      new Thread(() => {
        println(s"Thread started for job $job")
        println(s"Parameter: $parameter")
      })
    })

  threads.foreach(t => t.start())
  threads.foreach(t => t.join())

  println("Done!")
}

下面是程序的输出。注意在结尾没有“完成!”(-〉程序不会终止):

Thread started for job foo
Thread started for job bar

当我注解掉println(s"Parameter: $parameter")时,它正常工作,程序终止。因此,当从.map函数内部的局部变量的外部作用域中捕获参数时,问题可以得到解决:

...

val threads = jobs
  .map(job => {
    val param = parameter

    new Thread(() => {
      println(s"Thread started for job $job")
      println(s"Parameter: $param")
    })
  })

...

然后输出如预期:

Thread started for job foo
Parameter: Param
Thread started for job bar
Parameter: Param
Done!

为什么当我在线程中使用参数时,这个程序从不终止(-〉导致死锁)?
Scala/JVM有什么隐含的魔力?
我使用的是Scala 3.2

y0u0uwnf

y0u0uwnf1#

正如Levi在评论中指出的,问题来自扩展App,解决方案是使用一个main函数,This Answer提供了更多细节。
工作程序如下所示:

object MyApplication {
  def main(args: Array[String]): Unit = {
    val jobs = List("foo", "bar")
    val parameter = "Param"

    val threads = jobs
      .map(job => {
        new Thread(() => {
          println(s"Thread started for job $job")
          println(s"Parameter: $parameter")
        })
      })

    threads.foreach(t => t.start())
    threads.foreach(t => t.join())

    println("Done!")
  }
}

相关问题