public class LazySingleton { private static LazySingleton singleton; private LazySingleton() {} public synchronized LazySingleton getInstance() { if (singleton == null) { singleton = new LazySingleton(); } return singleton; } }
public class HungarySingleton { private static HungarySingleton singleton = new HungarySingleton(); private HungarySingleton(){} public static HungarySingleton getInstance(){ return singleton; } }
public class DoubleCheckSingleton { private static volatile DoubleCheckSingleton singleton; private DoubleCheckSingleton() {} public static DoubleCheckSingleton getSingleton() { if (singleton != null) { return singleton; } else { synchronized (DoubleCheckSingleton.class) { if (singleton == null) { singleton = new DoubleCheckSingleton(); } return singleton; } } } }
public class StaticInnerClassSingleton { private StaticInnerClassSingleton(){} private static class StaticInnerClass{ private static StaticInnerClassSingleton singleton = new StaticInnerClassSingleton(); } public StaticInnerClassSingleton getInstance(){ return StaticInnerClass.singleton; } }
public class EnumSingleton { private enum Singleton{ INSTANCE; EnumSingleton enumSingleton; Singleton(){ synchronized (this){ enumSingleton = new EnumSingleton(); } } } public EnumSingleton getInstance(){ return Singleton.INSTANCE.enumSingleton; } }
memory = allocate();//一、分配對象的內存空間 ctorInstance(memory);//二、初始化對象 instance = memory//三、設置instance指向剛剛分配的內存地址
在上面3行僞代碼2和3之間,可能會被重排序。重排序以後的順序可能變爲 1,3,2。在JVM規範中容許在單線程內,不會改變單線程程序執行結果的重排序。這個重排序在沒有改變單線程執行結果的前提下能夠提升程序的執行效率。可是這種寫法在多線程中會出現問題,if (singleton == null) 進行了判斷,可是若是線程T1,限制性了3,這時候instance不等於null,T2進來以後判斷singleton!=null,開始拿到這個對象直接使用,可是這個singleton對象尚未被初始化(ctorInstance)。那就是致使T2使用這個對象的時候出錯。以上就是若是singleton沒有加volatile致使的結果。因爲加了volatile,會禁止指令重排序,就不會出現上面的問題。因此這種寫法是安全的。java