普通懒汉式
class Singleton {
private Singleton(){}
private static Singleton single = null;
private static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
在多线程环境下可能创建多个实例,当两个线程同时获取single时都为null,都会进入if条件,所以可能创建多个实例
synchronized实现同步
class Singleton {
private static Singleton single = null;
private Singleton() {}
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (single == null) {
single = new Singleton();
}
}
return single;
}
}
同时只有一个线程可以进入同步代码块,但是实际上只有第一次当single为null的时候才需要加锁,上面代码每次都要加锁,性能不高
doule-check单例模式
class Singleton {
private static Singleton single = null;
private Singleton() {}
public static Singleton getInstance() {
if (single == null) {
synchronized (Singleton.class) {
if (single == null) {
single = new Singleton();
}
}
}
return single;
}
}
只有当single为null的时候才会进入同步块,解决了上面每次都要加锁的问题。但是还可能存在指令重排的问题。 single = new Singleton()可以分为几步:
- 给single分配空间
- 调用构造方法初始化single
- 将single指向分配的地址 正常顺序是1->2->3,如果指令重排后可能是1->3->2,那么在执行完3后single != null了,这时候2判断第一个if的时候为false,会直接返回single
加volatile
class Singleton {
private volatile static Singleton single = null;
private Singleton() {}
public static Singleton getInstance() {
if (single == null) {
synchronized (Singleton.class) {
if (single == null) {
single = new Singleton();
}
}
}
return single;
}
}
加volatile防止指令重排