2012-07-18 122 views
18

我有一个关于变量作用域的问题。静态方法和线程安全的局部变量

例如:

class A { 
    private static void test() { 
     // do something with local variables 
    } 
} 

现在我做两个线程,并为每个线程创建的A一个实例。

  1. 当我在每个线程中调用test(),我可以保证,test()是线程安全的?

  2. test()的本地变量在哪里存储?每个线程的堆栈?堆空间?

P.S.我知道静态在这种情况下完全没有意义。我在我们的遗留代码中找到它;我只是想确定我所知道的!

回答

28

局部变量存储在每个线程自己的堆栈中。这意味着线程之间永远不会共享局部变量。这也意味着所有本地原始变量都是线程安全的。

对象的本地引用有点不同。该参考本身不被共享。然而,引用的对象并不存储在每个线程的本地堆栈中。所有对象都存储在共享堆中。如果在本地创建的对象永远不会转义它创建的方法,则它是线程安全的。事实上,只要这些方法或对象都没有使传递的对象可用于其他线程,您也可以将它传递给其他方法和对象。

对象成员与对象一起存储在堆中。因此,如果两个线程在同一对象实例上调用方法,并且此方法更新对象成员,则该方法不是线程安全的。

线程安全检查:如果一个资源是在同一线程的控制下创建,使用和处理的,并且永远不会逃脱对该线程的控制,那么使用该资源是线程安全的。

来源:http://tutorials.jenkov.com/java-concurrency/thread-safety.html

+2

+1,但你肯定能“通”,(信号),对象给其他线程,但是创建它平时应“放弃所有权”的它,例如线程。通过使其自己的引用无效或通过创建另一个对象来覆盖它,以便两个线程永远不能在同一个对象上操作。如果没有完成,按照您的描述,该对象将被共享,并且需要锁定才能访问。 – 2012-07-18 06:31:40

+0

是的,出于这个原因,通过将参考归零来处置对象是个好主意。 – Erol 2012-07-18 06:33:32

+0

伟大的我正要问这个问题! – JohnMerlino 2014-06-30 21:27:26

0

对于编号1,我不知道test()做什么,所以我无法回答。如果他们修改类A的某个static变量,那么它可能不是线程安全的。如果沿途的两个线程都被赋予同一个对象的引用,则取决于对象的定义方式,它可能不是线程安全的。

对于数字2,局部变量在每个线程的堆栈中(或者至少在概念上就是这样),所以不用担心局部变量会被其他线程修改。

2

当我在每个线程中调用test()时,我可以保证test()是线程安全的吗?

是的,如果在test()方法中您正在使用 方法局部变量,它将是线程安全的。

test()中的局部变量存储在哪里?每个线程的堆栈?堆空间?

方法局部变量存储在每个线程自己的堆栈中。