单例模式DCL懒汉式为何要用volatile关键字?

singleton = new Singleton()这段代码其实不是原子性的操作,它至少分为以下3个步骤:

(1)singleton对象分配内存空间
(2)调用Singleton类的构造函数等,初始化singleton对象
(3)将singleton对象指向分配的内存空间,这步一旦执行了,那singleton对象就不等于null了
这里还需要知道一点,就是有时候JVM会为了优化,而做指令重排序的操作,这里的指令,指的是CPU层面的。

正常情况下,singleton = new Singleton()的步骤是按照1->2->3这种步骤进行的,但是一旦JVM做了指令重排序,那么顺序很可能编程1->3->2,如果是这种顺序,可以发现,在3步骤执行完singleton对象就不等于null,但是它其实还没做步骤二的初始化工作,但是另一个线程进来时发现,singleton不等于null了,就这样把半成品的实例返回去,调用是会报错的。

DCL使用volatile关键字,是为了禁止指令重排序,避免返回还没完成初始化的singleton对象,导致调用报错,也保证了线程的安全。

volatile作用:

  1. 保证被修饰的变量对所有线程的可见性。
  2. 禁止指令重排序优化。

 

public class SingleInstance {
    private SingleInstance() {}
    private volatile static SingleInstance INSTANCE;
    public static SingleInstance getInstance() {
        if (INSTANCE == null) {
            synchronized (SingleInstance.class) {
                if (INSTANCE == null) {
                    INSTANCE = new SingleInstance();
                }
            }
        }
        return INSTANCE;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值