(阿里巴巴手册)关于并发场景下,通过双重检查锁实现延迟初始化的优化问题隐患的记录

《阿里巴巴Java开发手册》中有这么一个推荐:
在这里插入图片描述
在这里插入图片描述
这种单例模式是我经常写的,看到竟然是反例,网上查了查,还是有根据的。
这样的问题在于初始化代码:

instance = new Singleton();

JVM会将这段代码分成三步去执行:

a.分配内存空间;

b.构造Singleton;

c.将instance指向构造的实例。

如果执行的过程是a->b->c的话,那上面的代码是没有问题的,但是有时JVM会基于***指令优化的目的将指令重排***,导致指令执行流程变为a->c->b。这样当线程A执行到4开始初始化单例对象的c流程时,线程B执行到1处,由于instance对象已经将内部指针指向分配的内存空间(即不为null),会直接返回未完全构造好的实例,从而出错。按照《手册》的说法,修改后的代码如下
在这里插入图片描述
由于volatile自带的“禁止指令重优化”语义,初始化语句只能按照a->b->c的顺序进行执行。

注:尽管这个问题看起来很简单,但是我在本地没有办法重演这个bug,这个bug出现的关键时刻在于线程A在执行a->c->b链的c时,线程B将构造完的instance返回并使用才会出错,但是一般的场景下是没有办法在这么短的时间间隔内捕获到这个间隔的。不过出于保险的目的,单例模式的我还是加上volatile修饰符比较好。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值