设计模式系列---两种懒汉式延迟加载单例模式
兴趣所致,上代码:
/** * 基于双重锁机制的延迟加载单例模式 * * @author Administrator * */ public class NotePadDoubleSingle { private static volatile NotePadDoubleSingle single = null; private NotePadDoubleSingle(){}; public static NotePadDoubleSingle getInstance (){ if(single == null){ synchronized (NotePadDoubleSingle.class) { if(single == null){ single = new NotePadDoubleSingle(); } } } return single; } } /** * 基于静态类加载的延迟加载单利模式 * * @author Administrator * */ class NotePadLoadSingle{ private NotePadLoadSingle(){}; private static class NotePadLoadSingleHolder{ public static NotePadLoadSingle single = new NotePadLoadSingle(); } public static NotePadLoadSingle getInstance(){ return NotePadLoadSingleHolder.single; } }
分析
DCL(Double check lock)添加volatile 修饰的原因:
首先分析,创建对象的过程,实例化对象一般分为三个过程。
1、分配内存空间。
2 、初始化对象。
3 、将内存空间地址赋值给对象的引用。
但是由于重排序的缘故,步骤2、3可能会发生重排序,其过程如下
1、分配内存空间
2、将内存空间的地址赋值给对应的引用
3、初始化对象
如果不加volatile的话,可能线程1在初始化的时候重排序了,线程2看到singleton != null,已经返回singleton,其实线程1还没有完成初始化,仅仅只不过是分配了内存空间而已!