java - Scala 在线程中对待 "sharing"局部变量的方式与 Java 不同?它是如何工作的?

标签 java multithreading scala

我对局部变量工作原理的心智模型是它们存储在堆栈中,每个线程都有自己的堆栈,线程之间无法访问堆栈。

在 Java 中,我实际上不确定如何修改衍生线程中的局部变量,因为编译器提示我无法在 lambda 或内部类中修改它。

但是,在 Scala 中我可以这样做:

implicit val ec = scala.concurrent.ExecutionContext.global

var i = 5

val f = Future {
  println((1, i))
  i = 6
  println((1, i))
}
val g = Future {
  println((2, i))
  println((2, i))
  println((2, i))
}
Await.result(f, 3.seconds)

并获得结果

(2,5)
(1,5)
(2,5)
(2,6)
(1,6)

线程#2 如何看到线程#1 的修改?

最佳答案

你完全正确。每个线程都有自己的堆栈,局部变量驻留在堆栈中。

这就是 Java 局部变量应该是 final 或实际上是 final 的原因。但是你可以使用一个众所周知的单元素数组技巧,这样指向数组的指针实际上是最终的并且驻留在堆栈中,但是数组的元素可以从闭包中更改。像这样:

int a[] = new a[0];
Thread t = new Thread(() -> {
    a[0] = 1;
});
//...

在 Scala 中,编译器会为你做类似的事情,并将它们放在堆上,而不是自己放在栈上。 (抱歉,无法编写一个简单的 Scala 示例并立即查看其字节码,但使用 javap -c 非常简单易读)

关于java - Scala 在线程中对待 "sharing"局部变量的方式与 Java 不同?它是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51690555/

相关文章:

java - 自定义谓词有时会返回随机结果

scala - 为什么这个删除警告与声明为元组的成员变量?

scala - 无法从 github 导入已安装的 scala/sbt 库依赖项

PreferenceChanged 方法中的 Java/Swing 堆栈溢出

java - 为什么 float 和 double lambda 参数仅限于 float value set,double value set?

java - 在 JDBC 准备语句中使用变量而不是参数索引

c# - C# 中的线程事件回调

java - 如何根据双击 JTable 的位置生成新面板?

multithreading - Cython Prange失败并显示致命Python错误: PyThreadState_Get: no current thread

.net - .NET/CLR上Scala中的改进泛型