从另一个线程修改局部变量意味着什么?

时间:2018-04-19 15:14:10

标签: multithreading scala jvm stack

我写了以下简单的应用程序:

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 个答案:

答案 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
}