在一個公衆號的大神文章中,看了一篇關於單例文章,特此記錄一下。
一、雙重校驗單例模式
代碼:
public class Singleton {
private Singleton() {} //私有構造函數
//關鍵:增加了一個 volatile 修飾符
private volatile static Singleton instance = null; //單例對象
//靜態工廠方法
public static Singleton getInstance() {
if (instance == null) { //雙重檢測機制
synchronized (Singleton.class){ //同步鎖
if (instance == null) { //雙重檢測機制
instance = new Singleton();
}
}
}
return instance;
}
}
說明:
正常建立對象,經過步驟:1、分配內存空間 2、初始化對象 3、設置對象指向剛分配的內存地址
如果沒有使用 volatile 修飾符,因爲JVM編譯器的指令重排機制,有可能導致在 new singleton() 方法建立對象的時候,命令順序改變,有可能A線程在建立對象的時候,執行了步驟1和步驟3,2還沒有執行,此時線程B執行的話,對象爲null,導致線程不安全。
volatile 修飾符就是爲了保證指令按照正常的順序執行,避免發生上面的情況。
PS:本文如果有錯誤,特請指出,便於修改學習!
二、靜態內部類實現單例模式
代碼:
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}