为什么局部变量是线程安全的?

249 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

前言

之前我们学习到,多个线程同时访问共享变量时,会导致并发问题。那么,如果将变量放在方法内部,是不是还会存在线程安全问题呢?如果不存在线程安全问题,那么为什么不会存在线程安全问题呢?今天,我们就带着这两个问题,来一起探索吧!

方法是如何被执行的?

例如,有三个方法 A、B、C,调用关系为 A 调用 B,B 调用 C。在运行时,会构建出相应的调用栈,我们可以用下图简单的表示这个调用栈:

image.png

每个方法在调用栈里都会有自己独立的栈帧,每个栈帧里都有对应方法需要的参数和返回地址。当调用方法时,会创建新的栈帧,并压入调用栈;当方法返回时,对应的栈帧就会被自动弹出。

也就是说:栈帧是在调用方法时创建,方法返回时“消亡”。

局部变量存放在哪里?

局部变量的作用域在方法内部,当方法执行完,局部变量也就没用了。可以这么说,方法返回时,局部变量也就“消亡”了。此时,我们会联想到调用栈的栈帧。局部变量就是存放在调用栈里的。此时,我们可以将方法的调用栈用下图表示:

image.png

局部变量会存放在栈里。如果一个变量需要跨越方法的边界,就必须创建在堆里。

调用栈与线程

每个线程都有自己独立的调用栈。 我们可以使用下图来简单的表示这种关系:

image.png

总结

方法里的局部变量,因为不会和其他线程共享,所以不会存在并发问题。这种解决问题的技术也叫做线程封闭