从其他线程修改局部变量的含义及线程间变量可见性疑问
从另一个线程修改“局部变量”的困惑解析
哈哈,这个误区太常见啦!先给你戳破核心问题:你代码里的v根本不是局部变量~
先搞清楚变量的存储位置
在Scala中,object Main extends App里定义的var v: Int = 0,是Main这个单例对象的成员变量,它存储在堆内存中。堆内存是所有线程共享的内存区域,所以子线程完全可以访问并修改这个变量。
而你说的“栈内存为每个线程单独分配”没错,但栈内存只存放方法内未被闭包捕获的局部变量,比如如果我们把代码改成这样:
object Main extends App { def run(): Unit = { // 这才是真正的局部变量,存在当前线程的栈上 var localV: Int = 0 // 但如果把它放到线程的lambda里,Scala会把它包装成闭包对象(存堆上) val t = new Thread(() => localV = 1) t.start() t.join() println(localV) } run() }
这里的localV原本是run方法的局部变量,但因为被线程的匿名函数捕获,Scala会自动把它包装成一个堆上的对象,所以子线程依然能修改它——这也侧面说明,真正栈上的纯局部变量,其他线程是根本访问不到的。
再看你的代码逻辑
你的代码里,子线程修改的是堆上的Main对象成员v,而且你调用了t.join()——这个方法会让主线程等待子线程完全执行完毕之后再继续往下走。所以当主线程执行println(v)的时候,子线程对v的修改已经完成,自然能看到更新后的1。
总结一下
- 别混淆对象成员变量和局部变量:你的
v是对象成员,存堆上,所有线程共享; - 栈内存只存线程私有的纯局部变量(未被闭包捕获),其他线程无法访问;
join()方法保证了主线程会等子线程操作完成,所以修改后的变量值对主线程可见。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

