从另一个线程修改本地变量是什么意思?

3
我写了以下简单应用程序:
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
    }
}
2个回答

8

v在这种情况下不是本地变量,而是Main单例对象的成员。

第二个示例的更新: 闭包() => v = 1被编译成一个匿名类,该类捕获它所依赖的所有变量。栈分配的原始类型被转换为堆分配的对象。 这里有详细解释: Scala中闭包的内存管理是如何工作的?


更新了我的答案。 - simpadjo

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接