面试中,面试官问起单例模式时,我们是否只乖乖地回答了七种单例模式呢
在单例模式的懒汉模式(线程安全实现)中,为什么需要更进一步地改为DCL(Double check)?这里其实涉及到Singleten对象在创建时的指令重排序问题。
Singleton = new Singleton();
抽象为jvm指令为
memory = allocate(); //1:分配对象的内存空间
initInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址
因为2、3指令并不互相依赖,jvm可能把指令优化为
memory = allocate(); //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址
initInstance(memory); //2:初始化对象
而volicate又是怎么防止指令重排序的呢?
答:volatile关键字通过“内存屏障”来防止指令被重排序。
下面是基于保守策略的JMM内存屏障插入策略:
在每个volatile写操作的前面插入一个StoreStore屏障。
在每个volatile写操作的后面插入一个StoreLoad屏障。
在每个volatile读操作的后面插入一个LoadLoad屏障。
在每个volatile读操作的后面插入一个LoadStore屏障。
关于内存屏障可以参考下文
内存屏障