2011-06-22 51 views
3

假設我有一個實用工具類,同步關注與Java中的靜態方法

public class Utility { 

    private Utility() {} //Don't worry, just doing this as guarantee. 

    public static int stringToInt(String s) { 
     return Integer.parseInt(s); 
    } 
}; 

現在,假設,在多線程應用程序,一個線程調用,Utility.stringToInt()方法和操作進入方法調用,另一個線程調用傳遞不同s的相同方法。 在這種情況下會發生什麼? Java是否鎖定靜態方法?

+0

這樣做的原因的問題是,我們收到不同的規則和值(和XML沒有固定的定義,並有可能到在同一時間的推移,這些XML同一服務的多個調用)的XML文件。 –

回答

10

這裏沒有問題。每個線程將使用自己的堆棧,因此不同的s之間沒有碰撞點。而Integer.parseInt()是線程安全的,因爲它只使用局部變量。

+0

我不擔心'整數。parseInt()',我擔心如果調用的結果帶來意想不到的結果。 –

+0

靜態方法只是在自己的堆棧上運行的一系列操作碼。堆棧不重疊,所以你很好。 –

+0

@The Elite ..:如前所述,所有線程都使用自己的堆棧。而且你知道,局部變量駐留在堆棧中,不像駐留在堆中的實例/類變量。 –

0

除非明確指定,否則不應該這樣做。此外,在這種情況下,不會有任何線程安全問題,因爲「s」是不可變的,並且也是本地方法。

0

您不需要同步,因爲變量s是本地的。

只有多個線程共享資源時,您才需要擔心,例如,如果s是靜態字段,那麼你必須考慮多線程。

3

Java不會鎖定靜態方法,除非您添加關鍵字​​。

請注意,當您鎖定一個靜態方法時,您將抓取該方法在其下實施的Class對象的Mutex,因此在靜態方法上同步將阻止其他線程進入任何其他「已同步」靜態方法。

現在,在你的例子中,你不需要在這種特殊情況下同步。那是因爲參數是通過複製傳遞的;因此,多次調用靜態方法將導致參數的多個副本,每個副本都在自己的堆棧幀中。同樣,同時調用Integer.parseInt(s)將分別創建自己的堆棧幀,並將s值的副本傳遞到單獨的堆棧幀中。

現在,如果Integer.parseInt(...)以非常糟糕的方式實現(它在parseInt執行過程中使用了靜態非最終成員;那麼將會有一個值得關注的重要原因,幸運的是, Java庫是比這更好的程序員

1

在你給出的例子中,線程之間沒有共享數據,也沒有數據被修改(你必須同時擁有這兩個線程的問題)


你可以寫

public enum Utility { 
    ; // no instances 

    public synchronized static int stringToInt(String s) { 
     // does something which needs to be synchronised. 
    } 
} 

這是有效地相同

public enum Utility { 
    ; // no instances 

    public static int stringToInt(String s) { 
     synchronized(Utility.class) { 
      // does something which needs to be synchronised. 
     } 
    } 
} 

然而,它不會標記方法爲同步和你,除非你正在訪問可以修改共享數據則不需要同步。