单例模式三(双重检查)

  懒汉式的延迟加载可以解决线程安全和节省内存,但又会引起性能不足。

  按照上一篇文章的代码,a,b多个线程执行情况下,如果a先进入了方法处于允许状态,那b线程则只能处于监听状态。

通过调式效果如下

之前是让其他线程在方法外面待着,那是否可以让它们也先进方法里面来等待呢?这就跟餐厅排队等一样,站在外面风吹日晒,不如先让顾客进大厅进行排队。

代码改版后的2.1

public class LazySingletion {
    private LazySingletion(){

    }
    private static   LazySingletion single;

    protected   static LazySingletion getInstance(){
        synchronized(LazySingletion.class){
            if(single == null ){
                single = new LazySingletion();
            }
        }
        return  single;
    }
}

  这里有人会产生疑问,这换汤不换药啊,还是需要等待。所以这段代码还有改进的余地。

  改进思路:1.可以先判断是否已经存才对象,再来考虑是否排队

 2.2版本

public class LazySingletion {
    private LazySingletion(){

    }
    private static volatile  LazySingletion single;

    protected   static LazySingletion getInstance(){
        if(single == null){
            synchronized(LazySingletion.class){
                if(single == null ){
                    single = new LazySingletion();
                }
            }
        }
        return  single;
    }
}

为了避免执行重排序问题,这里可以加了一个关键字 volatile。 

LazySingletion single = new LazySingletion();这行代码在源码上是一行,但是它在执行的过程却是多个阶段

1.分配内存空间,比如班上来了一位新同学,先提前安排一个地方。

2.初始化对象,给新同学配上桌子板凳,位置上并没有人。

3.对象指向内存地址。新同学真正来到学校并入座分配的位置,该位置真正有人坐。

这3个阶段不存在数据间的相互依赖,所以可以进行指令重排序。多线程情况下,重排顺序为1-3-2时,当判断if(single == null)时,执行到了第3步骤,地址不为空,因为该地址已经分配出去(座位虽然是空,但已经有属于的同学了) ,最后返回对象。由于并没有初始化完成,在使用该地址指引的对象时就会抛出异常(新同学还没有真正的来到教室入座),

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值