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