單例(Singleton)模式

最簡單的單例「餓漢式」 web

public class Singleton{安全

private static Singleton instance=new Singleton();
    //other fields
    private Singleton(){}
    public static Singleton getInstance(){
         return instance;
    }
    //other methods
}

出於性能等方面的考慮,但願延遲實例化單例對象(static 屬性在加載類時會被初始化),方案二應運而生,稱之爲「懶漢式」多線程

public class Singleton {

private static Singleton instance=null;
    // 私有構造方法,防止從外部使用 new 方法建立對象
private Singleton() {
    }
    public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
不幸的是,在高併發的環境中,getInstance()方法返回了多個指向不一樣的該類實例,也就是說:線程不安全。

線程安全寫法A
public class Singleton {

private static Singleton instance=null;
  // 私有構造方法,防止從外部使用 new 方法建立對象
private Singleton() {
  }
  public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
方案A中雖然實現了多線程的安全訪問,但在多線程高併發訪問狀況下,加上 synchronized關鍵字會使得性能大不如前。

線程安全寫法B併發

public class Singleton {

private static volatile Singleton instance=null;
  // 私有構造方法,防止從外部使用 new 方法建立對象
private Singleton() {
  }
  public static synchronized Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
方案B,咱們稱之爲 Double-Checked Locking (雙重檢查加鎖)模式。在此方案中,仍是使用 synchronized,只不過此次只是保證明例化的這段邏輯被一個線程執行。

前述的方法都存在小小的缺陷,有沒有一種既能實現延遲加載,又能實現線程安全的方案呢高併發

終極方案性能

public class Singleton{
     private Singleton(){}       private static class LazyHolder{         private static final Singleton instance = new Singleton();     }      public static Singleton getInstance(){         return LazyHodler.instance;     }}
相關文章
相關標籤/搜索