线程安全的懒汉式
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;
}
}
第一次检查instance==null是为了防止实例已经被创建好时,重复去创建,同时防止不必要的加锁操作。
增加第2次检查instance==null:当一个线程正在执行new Singleton()创建实例,其他线程执行到第一个if (instance==null)之后,而在synchronized之前,即其他线程已经闯过了第一次检查,接着执行new Singleton()的线程创建好了实例,并释放了锁,那么其他线程便可以进入synchronized代码块中去再次创建实例,第2次检查instance==null就是为了防止这种情况下重复创建实例。
volatile是为了使instance=new Singleton(),避免指令重排。
- 给 instance 分配内存 new
- 调用 Singleton 的构造函数来初始化成员变量 Singleton()
- 将instance引用指向分配的内存空间 = (执行完这步 instance 就为非 null 了)
如果按1-3-2的顺序执行,执行完3时,其他线程就能拿到实例了,但此时2还没有执行,创建的实例是有问题的。
线程安全的饿汉式
public class Singleton{
//类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。
Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。