2010-06-01 146 views
4

下面的代碼是線程安全的嗎?靜態方法和線程安全

public static Entity getInstance(){ 
//the constructor below is a default one. 
    return new Entity(); 
    } 

回答

5

假設構造函數本身是線程安全的,這很好。

這將是一個構造是線程安全的極不尋常的,但有可能...即使它呼籲Entity默認的自動生成的構造,基本構造可能不是線程安全的。我不是說這是有可能的,只是可能:)

基本上有適用於靜態方法實例方法構造沒有神奇的線程安全。除非應用同步,否則它們都可以同時在多個線程上調用。如果他們沒有獲取或更改任何共享數據,他們一般都是安全的 - 如果他們訪問共享數據,您需要更加小心。 (如果共享數據是不可變的還是隻讀的,這是一般正常 - 但如果一個線程將被變異它,你需要非常小心。)

只有靜態初始化(靜態變量和static { ... }塊初始化表達式直接在一個類中)有特殊待遇 - 虛擬機確保它們只執行一次,阻止正在等待類型初始化的其他線程。

+0

你可以定義,你是什麼意思的'共享數據'?我的理解是,這將是「Enity」類的一些靜態字段! – Akshat 2015-04-11 08:48:20

+0

@Akshat:我的意思是任何由多個線程訪問和修改的數據。 – 2015-04-11 09:32:17

+0

好吧,假設在這個例子中,如果構造函數初始化了一些最終的非基元字段,那麼'getInstance()'方法是否需要爲線程安全進行同步? – Akshat 2015-04-11 09:37:56

4

這取決於實體構造函數的細節。如果實體構造函數修改共享數據,則不是。

0

多個線程可以調用此方法,並且每個線程都將獲得一個「實體」的唯一實例。所以這種方法'本身'是線程安全的。但是如果在構造函數中或者在一個不是線程安全的超級構造函數中存在代碼,那麼無論如何你都可能會遇到安全問題。

1

線程安全是關於訪問不同線程之間的共享數據。您示例中的代碼本身不訪問共享數據,但它是否是線程安全的取決於構造函數是否訪問可以在不同線程之間共享的數據。

在併發編程方面存在很多細微而棘手的問題。如果您想了解Java中的線程安全性和併發編程,那麼我強烈推薦Brian Goetz編寫的Java Concurrency in Practice

2

這可能是線程安全的,但有什麼意義?如果您只是使用工廠方法重定向到默認構造函數,那麼爲什麼不首先使用構造函數呢?所以問題是:你想達到什麼目標?名字getInstance()建議一個單身人士(至少這是常見的做法),但你顯然沒有單身人士在那裏。如果你想一個單身,使用靜態內部類持有人是這樣的:

public class Singleton { 

     private Singleton() { 
     } 

     public static Singleton getInstance() { 
      return InstanceHolder.INSTANCE; 
     } 

     private static final class InstanceHolder { 

      public static final Singleton INSTANCE = new Singleton(); 

     } 
    } 

,但如果你不這樣做,爲什麼這樣的工廠方法煩心,因爲你不加入任何值(方法名語義,對象池,同步等)通過它