2012-07-18 163 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()中的局部變量存儲在哪裏?每個線程的堆棧?堆空間?

方法局部變量存儲在每個線程自己的堆棧中。