2010-12-05 98 views
1

下面的片段是直線前進,Singleton模式

public MyClass getInstance() { 
    if(uniqueInstance == null) { 
     uniqueInstance = new MyClass(); 
    } 
    return uniqueInstance; 
} 

什麼是以下一種呢?

public MyClass getInstance() { 
    if(uniqueInstance == null) { 
     synchronized(MyClass.class) { 
      uniqueInstance = new MyClass(); 
     } 
    } 
    return uniqueInstance; 
} 

回答

5

這是一個很差的嘗試,以使其線程安全,以防止由至少兩個線程同時進入if塊造成的競爭條件。

更安全一點的方法是添加額外的空檢查,也稱爲double-checked locking

public MyClass getInstance() { 
    if (uniqueInstance == null) { 
     synchronized(MyClass.class) { 
      if (uniqueInstance == null) { 
       uniqueInstance = new MyClass(); 
      } 
     } 
    } 
    return uniqueInstance; 
} 

但是,我通常更喜歡Just Create One pattern而不是Singleton。

+0

「更安全一點」...我不太確定:http://www.google.ca/search?q=double+checked+locking+is+broken – 2010-12-05 06:05:48

3

這是一個線程安全的保險。

從和javaworld文章here

同步的方法保證 是對方法的調用不能 中斷。

主要的想法是,如果你沒有在synchronized塊是可能的2個線程調用的getInstance並重新初始化對象,從而可能丟失任何狀態數據(如果你甚至應該有狀態數據一個單身人士)

1

第二個做同樣的事情,除了:如果您使用第一個,如果創建一個新的MyClass需要一定的時間,並且在此期間,其他人也會調用MyClass.getInstance() ?你可能會結束兩個實例。第二個版本鎖定實例化行,這樣如果另一個類嘗試同時調用,它將等到第一個完成。

3

恕我直言,你應該首先從最簡單的選項開始。最簡單的單例是帶有一個條目的枚舉。鑑於類是負載懶惰,這仍然會給你懶加載,除非直接引用類,這不容易發生意外。

enum Singleton { 
    INSTANCE; 
} 

爲避免意外加載,您可以使用內部類。

class Singleton { 
    static class SingeltonHolder { 
     static final Singleton INSTANCE = new Singleton(); 
    } 
    public static Singleton getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

注意;這兩個解決方案都不需要同步,因爲它們使用類加載是線程安全的事實。

總之;有些情況下需要鎖定,但不要使它比需要更復雜。