【设计模式】单例模式双层校验(DCL)与 volatile 的关系

6 篇文章 0 订阅
2 篇文章 0 订阅

这是一道美团的面试题

DCL单例(Double Check Lock)到底需不需要 volatile

其实就是问:private static volatile Singleton singleton = null; 中的 volatile 有没有必要加?

代码

public class Singleton {
    // 使用volatile保证了多线程访问时singleton变量的可见性,
    // 避免了初始化时其他变量属性还没赋值完时,被另外线程调用
     private static  volatile  Singleton singleton = null;
     
	// 定义一个私有构造,防止通过new去实例化
     private Singleton(){}

     public static  Singleton getSingLeton(){
         if(singleton == null){
             synchronized (Singleton.class){
                 if(singleton == null){
                     singleton = new Singleton();
                 }
             }
         }
         return singleton;
     }
}

为了理解这个问题,得深入理解对象创建得过程(new)
比如这个代码

    public static void main( String[] args )
    {
        Object o = new Object();
    }
 0: new #1;   (半初始化)
 4: invokespecial #1 <java/lang/Object.<init>>  (调用构造方法,实例变量赋值)
 7: astore_1   (与对象构建链接,建立联系)

在这里插入图片描述

对象 new 的过程可以分为三步

1)申请一块内存, 处于半初始化状态,如果有成员变量则赋上默认值

2)调用对象得构造方法

3)把 o (栈上得引用)与实际对象建立关联

但 CUP 会发生指令重排序得现象。
正常的对象生成 是 1-》2-》-》3
重排序了则 1 -》3-》2

后果是什么呢?
A 线程 初始化把对象初始化一半,且建立关联了。
这时候 B 线程来了,欸,它一看这个对象不为 null ,那么它就拿来用了。

if(o !=null) xxx -> 使用了一个半初始化对象

所以问题就是出在这里!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值