简述双重检查锁定模式(Double-Checked Locking Pattern)

双重检查锁定模式(Double-Checked Locking Pattern)是一种在多线程环境中用于减少锁开销的技术,尤其常见于实现单例模式时。其核心思想是在获取实例前进行两次检查:第一次检查是在没有同步的情况下检查实例是否已经创建,如果已创建则直接返回实例;如果没有创建,则进入第二次检查,这次检查在同步块内部执行,确保只有一个线程能够创建实例。

具体步骤如下:

  1. 第一次检查:线程进入getuniqueInstance ()方法时,首先检查实例(uniqueInstance )是否已经初始化过。如果是,那么直接返回实例,这样后续对该方法的调用就不需要执行下面的同步代码,从而减少了同步的开销。
  2. 同步检查:如果第一次检查发现实例未被初始化,这时才进入同步代码块。在同步块内部再次检查实例是否已被其他线程创建(这是“双重检查”的由来)。这一步是为了确认在进入同步块之前的短暂时间里,没有其他线程已经创建了实例。
  3. 创建实例:如果在同步块内部的第二次检查发现实例依然为null,那么就在该同步块内初始化实例。

这是正常的同步方法:

public class UniqueInstanceManager {
    private static UniqueInstanceManager uniqueInstance = null;

    private UniqueInstanceManager() {
    };

    public static synchronized  UniqueInstanceManager getUniqueInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new UniqueInstanceManager();
        }
        return uniqueInstance;
    }
}

但是这种同步方式在非静态的时候会带来额外的开销。

所以我们把sychronized加在if(uniqueInstance ==null)判断语句里面,保证uniqueInstance 未实例化的时候才加锁,减少开销。

public class UniqueInstanceManager {
    private static UniqueInstanceManager uniqueInstance = null;

    private UniqueInstanceManager() {}

    public static UniqueInstanceManager getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (UniqueInstanceManager.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new UniqueInstanceManager();
                }
            }
        }
        return uniqueInstance;
    }
}

这种模式试图平衡资源消耗和线程安全,通过减少对同步代码块的访问次数来提高性能,同时确保线程安全。然而,这种模式在早期的Java版本中可能存在内存模型问题,导致可能初始化不完整对象的危险。Java 5及以后版本通过增加 volatile 关键字来解决了这个问题,确保了实例的可见性和禁止指令重排序,正确的双重检查锁定模式实现应该像这样:

public class UniqueInstanceManager {
    private static volatile UniqueInstanceManager uniqueInstance = null;

    private UniqueInstanceManager() {}

    public static UniqueInstanceManager getUniqueInstance() {
        if (uniqueInstance == null) {
            synchronized (UniqueInstanceManager.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new UniqueInstanceManager();
                }
            }
        }
        return uniqueInstance;
    }
}

在这个修正后的版本中,uniqueInstance 变量被声明为 volatile,以确保多线程环境下的正确可见性和有序性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值