我写了以下简单的应用程序:
object Main extends App {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
我感到困惑的是,我们从另一个线程修改局部变量......并且该修改(由另一个线程进行(在主线程中可见。
我认为局部变量总是驻留在堆栈中(堆栈内存底部指向rsp
寄存器(。我认为堆栈内存是为应用程序中的每个线程分配的。
更新:即使我们按如下方式修改应用程序,它也会打印相同的内容:
object Main {
def main(args: Array[String]) = {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
}
v
不是局部变量。它是Main
单调对象的成员。
第二个示例的更新:闭包() => v = 1
被编译成一个匿名类,该类捕获它所依赖的所有变量。堆栈分配的基元将转换为堆分配的对象。这里详细解释:Scala 中闭包的内存管理是如何工作的?
这样做的目的是将看似堆栈的对象转换为堆对象。 在Java中,你可以使用数组1来做到这一点,而不需要像Scala那样添加特殊类。
public static void main(String... args) {
int[] v = { 0 };
Thread t = new Thread(() => v[0] = 1);
t.start();
t.join();
println(v[0]); //prints 1
}