Java 单例模式双重校验锁变量

本文详细解释了双重校验锁在单例模式中的应用,通过两次检查和volatile关键字确保线程安全,避免指令重排序带来的问题,提高性能。

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

【悲观锁】Java 线程八锁

【线程】Java线程状态的转换

【悲观锁】Synchronized和ReentrantLock的区别

【线程方法】多线程下 wait、notify、park、unpark 和 await、signal 的区别

【内存】Java中的volatile

【设计模式-单例模式】Java 单例模式双重校验锁变量

【CAS-乐观锁】AtomicInteger

【乐观锁】AtomicReference

【设计模式-享元模式】Java 享元模式自定义连接池

【线程池】自定义线程池

【线程池】ThreadPoolExecutor 线程池

【线程池】Executeror 构建线程池的方法

【线程池】ThreadPoolExecutor 的拒绝策略

【悲观锁】主要的 AQS 方法

【悲观锁】ReentrantReadWriteLock

【同步工具】StampedLock

【同步工具】CountDownLatch

【同步工具】CyclicBarrier和CountDownLatch的区别

线程安全集合类

LinkedBlockingQueue 怎么实现的线程安全

双重校验锁(DoubleCheck)是一种在多线程环境下延迟加载并保证单例对象的创建的方法(懒汉模式)。

public 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;
    }
}

这里使用了 volatile 修饰 instance 变量,以确保多线程环境下对 instance 的读写操作是原子的,并且防止指令重排序。

1、第一次检查(非空判断): 在进入同步块之前,先检查 instance 是否为 null。如果 instance 已经被初始化,就直接返回当前的实例,避免进入同步块,提高性能。若将同步锁直接加到方法上,则每次调用该方法都会争抢锁,并且进入和退出同步块都需要发生上下文切换的开销。

2、第二次检查(非空判断): 在同步块内,再次检查 instance 是否为 null。避免初次创建时多个线程都通过了第一次检查,再依次进入同步块时,可能会重复创建实例。这是为了确保其他线程在当前线程获取锁之前已经创建了实例,避免重复创建实例。

3、volatile则是防止防止指令重排序

假设线程A首先执行 getInstance() 方法,然后执行了双重检查中的第一次检查,判断 instancenull,进入同步块,但在同步块内的第二次检查之前,线程B也执行了 getInstance() 方法,由于线程A还未完成实例化,线程B也会通过第一次检查,然后等待线程A执行完同步块。

此时,如果没有使用 volatile 关键字修饰 instance,那么在线程A执行 instance = new Singleton(); 这一步时,可能会发生指令重排序,导致实例在内存中的分配和初始化的顺序被颠倒

  1. 分配内存空间给 instance
  2. 在内存空间中创建 Singleton 对象
  3. instance 指向分配的内存空间

在多线程环境下,线程B可能在线程A执行完第一步和第二步之后,在同步块内的第二次检查时,发现 instance 不为 null,于是直接返回了一个未完全初始化的实例,导致错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值