定義:java
優勢:數據庫
缺點:設計模式
使用場景:安全
關鍵點:bash
public class Singleton {
private static Singleton singleton = null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
複製代碼
若是兩個線程同時執行到singleton == null 的判斷的時候,兩個線程條件都知足,會出現建立兩個對象的狀況,違反了單例只建立一個對象的原則。網絡
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
複製代碼
public class Singleton {
private static Singleton singleton = null;
private Singleton(){
}
public synchronized static Singleton getInstance(){
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
複製代碼
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
複製代碼
singleton = new Singleton() 不是原子操做,這段代碼會編譯成多條指令
(1)將對象new出來,給Singleton分配內存空間
(2)調用Singleton構造函數,初始化成員變量
(3)將singleton指向分配的內存,此時singleton就不爲空了
java編譯器容許指令亂序執行,因此二、3步執行順序沒法保證,就可能線程B執行了這段代碼,singleton指向了內存空間,可是成員變量還沒初始化完。此時若是線程A經過singleton== null進行判斷,發現對象不爲空,拿對象去使用,可是成員變量還沒初始化完,就會出錯。多線程
被volatile關鍵字修飾,可以保證內存可見性和禁止進行指令重排序,經過該特性保證了singleton = new Singleton()的指令執行順序函數
public class Singleton {
private Singleton() {
}
private static class SingletonInner {
private static final Singleton sInstance = new Singleton();
}
public static Singleton getInstance() {
return SingletonInner.sInstance;
}
}
複製代碼
public enum Singleton{
SINGLETON;
}
複製代碼
private Object readResolve() throws ObjectStreamException {
return sInstance;
}
複製代碼
參考資料:優化