2012-03-03 34 views
10

我有一個關於Java中的多線程方法調用的問題。比方說,我們有一個單身的對象,它的類聲明如下:同時調用單身對象的Java方法

public class SomeClass { 
    public void someMethod(SomeValueObject object) { 

     if (object.condition1) { 
      ... 
     } 
     if (object.condition2) { 
      ... 
     } 
     if (object.condition3) { 
      ... 
     } 

    } 
} 

我想知道,如果這單對象被同時訪問和調用不同SomeValueObject情況下它的someMethod,是有機會一些隨機線程更改參考對象爲另一個線程的方法調用和搞砸的東西?那麼在方法範圍內創建的字段呢? 我沒有意識到,是否爲調用該方法的每個線程創建了單獨的Method上下文,或者所有調用該線程的線程的Method上下文都是相同的?如果是後一種情況下,我想我需要線程安全的同步關鍵字,或使用不同的SomeClass的情況下,爲每個線程(如果我需要在內存優化執行速度更快)。你能幫我解釋一下嗎?

P.S.謝謝你們所有的答案!

回答

13

如果一切都是本地的,你的方法是線程安全的。每個線程在堆棧上都有自己的對象參數,它們不會互相干擾。

你可以有併發的問題,如果兩個線程調用這個方法與同一個對象作爲參數,或者如果兩個這些對象共享一些狀態,但是這不是單身的問題。這是共享狀態的問題,必須正確同步。

良好的經驗法則:無狀態對象是線程安全的。具有不可變狀態的對象是線程安全的。如果不能正確同步對共享狀態的訪問,那麼具有可變狀態的對象就不是線程安全的。

8

不,線程將無法更改不同線程的局部變量。

在所述方法的範圍內創建的所有變量[局部變量] - 包括參數被分配特定的線程的堆棧上,並因此不是兩個線程之間共享。

但是 - 所有類的字段是不安全的,如果一個線程改變了他們 - 這將在所有反映。

3

每個線程都有自己的執行堆棧。該存儲區包含所有局部變量和方法參數。當兩個線程同時執行相同的代碼時,兩者都使用不同的堆棧。

因此,不可能通過在不同的線程來改變方法參數或局部變量的值。

2

方法本質上是一段代碼。當一組線程調用一個方法時,每個線程的棧上都存在一個獨立的方法副本,所以局部變量不會互相干擾。

如果附加地,所有的參數是不同的每個線程,則有完美隔離,除非你的方法是在其內部碼附加共享數據進行操作。

3

其他人說的。雖然吹毛求疵:Java中只有當地的原始變量和參數(INT,長,布爾等)在棧上分配的所有其他對象被分配在堆中,只引用存儲在堆棧上。但其他人說,每個方法的調用都會看到它自己的局部變量副本。

請注意,作爲參數傳遞的對象(與基元相對)並不一定對每個調用都是唯一的,因爲objet參數只是引用。因此,如果您將相同的輸入對象傳遞給該方法兩次,那麼兩者將在相同的輸入上運行。