You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从其他线程修改局部变量的含义及线程间变量可见性疑问

从另一个线程修改“局部变量”的困惑解析

哈哈,这个误区太常见啦!先给你戳破核心问题:你代码里的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:04:02