单例模式
双重校验+volatile (线程安全)
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
volatile可以禁止JVM的指令重排。比如instance = new Singleton();其实分三步:1. 为新实例分配内存 2. 初始化新实例 3. 将instance指向新实例的内存地址。由于JVM具有指令重排的特性,执行顺序有可能变成1>3>2。这在单线程环境下没问题,但多线程环境下会导致某线程获得未初始化的实例。如线程T1执行了1和3,此时T2调用getInstance()发现instance不为空并返回instance,但此时instance指向的空间还未初始化。
静态内部类 (线程安全)
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
当调用getInstance()时内部类才被加载。