面试题答案
一键面试- 第二次检查的原因:
- 第一次检查
if (singleton == null)
是为了在多线程环境下,避免不必要的同步开销。当多个线程同时访问getInstance
方法时,如果已经有实例创建,大部分线程可以直接返回实例,而不需要进入同步块。 - 然而,当第一个线程通过第一次检查进入同步块,在创建实例之前,第二个线程可能也通过了第一次检查(因为此时实例还未创建)。所以需要在同步块内进行第二次检查
if (singleton == null)
,确保只有一个线程创建实例。
- 第一次检查
- 省略第二次检查的问题:
- 如果省略第二次检查,当多个线程同时通过第一次检查进入同步块后,每个线程都会创建一个实例,这样就无法保证单例模式的唯一性,违背了单例模式的初衷。
示例代码如下:
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
变量的可见性和禁止指令重排序,防止在实例创建过程中出现问题。