2014-02-20 29 views
-2

有人問我在接受採訪時,以檢查其中的聲明singleton類的以下2種方式是更好地與合適的人reasons.Can請分享一些想法哪一個是更好的單身人士,爲什麼?

public static Singleton getSingleInstance() { 
    if (singleInstance == null) { 
     synchronized (Singleton.class) { 
      if (singleInstance == null) { 
       singleInstance = new Singleton(); 
      } 
     } 
    } 
    return singleInstance; 
} 

OR 

public static synchronized Singleton getSingleInstance() { 
    if (singleInstance == null) { 
     singleInstance = new Singleton(); 
    } 
    return singleInstance; 
} 
+0

http://en.wikipedia.org/wiki/Singleton_pattern維基百科解釋得比其他任何地方都好得多 – spiderman

+1

我對#2的投票 - 導致'空'檢查在同步塊的上下文內完成......更好解決方案將會使用'枚舉'... – MadProgrammer

+0

第一個會更好。 http://en.wikipedia.org/wiki/Double-checked_locking – anonymous

回答

0

由於這是一個面試問題,我認爲他們打算去到#1,因爲它避免了大部分時間的同步。

0

答案取決於什麼更重要,性能或代碼易讀性。對於性能,第一個更好[2],但爲了易讀性,第二個更好,因爲更少的代碼行更容易理解和證明沒有錯誤。

[2]性能取決於易失性讀取的速度,相比於獲取定義單例方法的類的監視器,假設該方法被多次調用。我沒有任何量化的證據,但我會認爲前者更好。

對於它的價值,Apache的公地LazyInitializer使用第一個(http://commons.apache.org/proper/commons-lang/apidocs/src-html/org/apache/commons/lang3/concurrent/LazyInitializer.html):

@Override 
public T get() throws ConcurrentException { 
    // use a temporary variable to reduce the number of reads of the 
    // volatile field 
    T result = object; 

    if (result == null) { 
     synchronized (this) { 
      result = object; 
      if (result == null) { 
       object = result = initialize(); 
      } 
     } 
    } 

    return result; 
} 
0

完全取決於你的需求。

在這種情況下 - 第一個問題之外,第一個問題沒有正確地保護測試(如果應該在同步之內,或者在測試之後但在您之前,您冒着其他人改變它的競爭條件已經完成了對測試結果的處理),所以你可以結束兩個實例 - 在JIT完成之後,這兩個實例可能是等價的。

但是,一般來說,同步方法的問題往往是它們是過度同步的。他們中的許多人持有他們的鎖超過絕對必要的時間,並可能會通過強制其他線程等待更長時間來降低性能。同步應該在使操作原子化所需的最短時間內完成,並且通常可以將其限制爲幾條關鍵線而不是整個方法。

另一方面...有時最好不要讓班級線程安全。散列表是線程安全的; HashMaps(新的替代)不是。這是因爲獲得鎖是一個相對昂貴的過程,尤其是在多處理器環境中,而在真實世界的代碼中,如果需要使用threadsafety,它通常希望覆蓋的不僅僅是單個hashmap訪問,因此鎖定在此級別通常比浪費更有幫助。

相關問題