MST

星途 面试题库

面试题:Java双重检查锁定单例模式中的空指针问题

请简述在Java双重检查锁定单例模式实现中,为什么在第一次检查实例是否为空后还需要第二次检查?如果省略第二次检查可能会出现什么问题?
13.0万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 第二次检查的原因
    • 第一次检查 if (singleton == null) 是为了在多线程环境下,避免不必要的同步开销。当多个线程同时访问 getInstance 方法时,如果已经有实例创建,大部分线程可以直接返回实例,而不需要进入同步块。
    • 然而,当第一个线程通过第一次检查进入同步块,在创建实例之前,第二个线程可能也通过了第一次检查(因为此时实例还未创建)。所以需要在同步块内进行第二次检查 if (singleton == null),确保只有一个线程创建实例。
  2. 省略第二次检查的问题
    • 如果省略第二次检查,当多个线程同时通过第一次检查进入同步块后,每个线程都会创建一个实例,这样就无法保证单例模式的唯一性,违背了单例模式的初衷。

示例代码如下:

public class Singleton {
    private static volatile Singleton singleton;
    private Singleton() {}
    public static Singleton getInstance() {
        if (singleton == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (singleton == null) { // 第二次检查
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

这里 volatile 关键字用于保证 singleton 变量的可见性和禁止指令重排序,防止在实例创建过程中出现问题。