2013-03-20 78 views
5

使用雙重檢查鎖定習慣用於單例模式會更好嗎?或者一個同步的方法?使用雙重檢查鎖定習慣用於單身模式是否最佳?

即:

private static volatile ProcessManager singleton = null; 

public static ProcessManager getInstance() throws Exception { 

    if (singleton == null) { 
     synchronized (MyClass.class) { 
      if (singleton == null) { 
       singleton = new ProcessManager(); 
     } 
     } 
    } 
    return singleton; 

}

private static processManager singleton = null; 

public synchronized static processManager getInsatnce() throws Exception { 

    if(singleton == null) { 
      singleton = new processManager(); 
    } 

    return singleton 
} 
+0

有兩個嵌套IFS沒有任何東西之間,就像在你的第二段代碼中一樣,沒有任何意義。 – Jesper 2013-03-20 14:52:14

+4

以上都不是,如[本答案](http://stackoverflow.com/a/15498689/1103872)中對您自己以前的問題所述。 – 2013-03-20 14:52:41

+0

在你的第二個例子中,由於你已經在關鍵部分 – Grimmy 2013-03-20 14:54:52

回答

0

基本上,你的第二個選項添加沒有額外的保障。

您經常檢查,但它們之間仍可能發生併發訪問,因此,您正在減少發生兩個實例的可能性,但不會消除它。

6

有ClassLoader的爲你做的工作:

/* 
    * This solution takes advantage of the Java memory model's guarantees about class initialization 
    * to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it 
    * is needed. That means that the first time getInstance is called, mySingletonServiceLoader 
    * will be loaded and instance will be created, and since this is controlled by ClassLoaders, 
    * no additional synchronization is necessary. 
    */ 
    public static DocumentService getInstance() { 
     return mySingletonServiceLoader.INSTANCE; 
    } 

    private static class mySingletonServiceLoader { 
     static DocumentService INSTANCE = new DocumentService(); 
    } 
} 
0

第一個選項。

有創建單一實例的多個版本的能力...

getInstance()調用的實例檢查null,然後立即構造,如果它爲空,然後instance返回。

它應該是線程安全的。

也請參考this也。

0

第一個選項是正確的雙重檢查鎖定的實現,但如果在ProcessManager的類,但的getInstance沒有更多的公共方法,那麼所有你需要的是

public class ProcessManager { 
    private static ProcessManager instance; 
    static { 
     instance = new ProcessManager(); 
    } 

    private ProcessManager() { 
    } 

    public static ProcessManager getInstance() { 
     return instance; 
    } 
} 

類將被加載並在第一ProcessManager的初始化.getInstance()調用

0

如果需要延遲加載,我會堅持雙重檢查而不是同步方法。最後,問題是,volatile vs. synchronized

揮發性,簡單地讓所有的訪問(讀取或寫入)到volatile變量發生到主內存,有效地把揮發性可變出CPU緩存。這對於一些只需要變量可見性正確且訪問順序不重要的操作而言可能很重要。

一旦實例被初始化,同步塊將不會被執行(但是競爭條件)。要支付的唯一併發成本是對易失性變量的單次讀取。

注意,在有效的Java布洛赫說,在一個局部變量加載揮發性場增強性能(據我所知,是因爲有較少的揮發性讀取)

public static ProcessManager getInstance() throws Exception { 
    ProcessManager result = singleton; 
    if (result == null) { 
    synchronized (MyClass.class) { 
     result = singleton; 
     if (result == null) { 
      singleton = result = new ProcessManager();    
     } 
    } 
    return result; 
} 
相關問題