单例模式之双重校验锁分析

之前写过单例模式,但是没有对双重校验锁进行详细分析,今天就来分析一下

@NoArgsConstructor
public class Singleton {
//     volatile 作用:
//     1、保证变量可见性;
//     2、禁止指令重排序;
//     instance 会经过三个步骤: 1、为instance分配内存空间 2、调用构造函数初始化instance 3、为instance分配内存地址
//     假设没有使用volatile,因为这个cpu会对指令进行排序,那么顺序可能会变成 1、3、2
//     那么在进行判断的时候,会导致instance==null 结果是false,实际上instance还没有被实例化,这时候使用的时候回报空指针异常。
    private static volatile Singleton instance;


    public static Singleton getInstance() {
        // 此处的instance判断是为了节省线程时间,防止每个线程都走加锁逻辑。假设线程A和线程B同时进来,那么会走后面的if判断。
        // 之后线程A实例化instance之后,线程B也获取到锁,发现已经创建了instance,会直接返回,线程C执行的时候在第一个if判断发现instance已经实例化了,就不会走加锁逻辑了。
        if (instance == null) {
            synchronized (Singleton.class) { // 假设有三个线程A,B,C,三个线程同时到达这里,由于加了同步锁,因此只会有一个线程获取到锁。那么假设线程A获取到锁,线程B,C在此等待
                if (instance == null) { // 这一步判断instance为空,进行实例化。那么,假设没有这个if判断,在线程A执行完成之后,线程B,C进来之后会对instance进行再度实例化。
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值