我写了以下简单的应用程序:
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
}
}
答案 0 :(得分:8)
v
不是局部变量。它是Main
单一对象的成员。
第二个例子的更新:
Closure () => v = 1
被编译成一个匿名类,捕获它依赖的所有变量。堆栈分配的原语被转换为堆分配的对象。
这里详细解释:
How does the memory management of closures in Scala work?
答案 1 :(得分:2)
这样做是将看似堆栈对象的内容转换为堆对象。在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
}