单例双重锁的原因

本文详细分析了Java单例模式中双重锁的原因。首先,第一重锁避免了多个线程同时进入实例化区域,减少不必要的线程阻塞。其次,第二重锁确保在instance为null时只有一个线程能实例化单例,防止多线程环境下产生多个实例。双重锁设计旨在保证线程安全的同时提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

原因分析
如果有两个线程同时到达,即同时调用getInstance() 方法,此时由于instance== null ,所以很明显,两个线程都可以通过第一重的 instance== null ,进入第一重 if语句后,由于存在锁机制,所以会有一个线程进入 lock 语句并进入第二重 instance== null ,另外的一个线程则会在lock 语句的外面等待。
而当第一个线程执行完new SingleTon()语句后,便会退出锁定区域,此时,第二个线程便可以进入lock 语句块,此时,如果没有第二重instance== null 的话,那么第二个线程还是可以调用 new SingleTon()语句,这样第二个线程也会创建一个SingleTon实例,这样也还是违背了单例模式的初衷的,所以第二重判断必须存在。
在没有第一重instance == null 的情况下,也是可以实现单例模式的?那么为什么需要第一重 instance == null呢?
都要判断是否为空,且判断是否为空之前,都要先加同步锁,如果线程很多的时候,就要先等待加了同步锁的线程运行完毕,才能继续判断余下的线程,这样就会造成大量线程的阻塞,且加锁是个非常消耗时间的过程,应该尽量避免(除非很有必要的时候)。

总结:
第一重锁作用:避免造成大量线程阻塞,避免性能消耗。
第二重锁作用:避免 instance== null时,第一个线程实例化后,进入阻塞状态的线程被唤醒后仍会进行实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值