饿汉式由于提前创建好对象,天生是线程安全的
public class HurryBank {
private HurryBank(){
}
private static final HurryBank INSTANCE = new HurryBank();
private static HurryBank getInstance(){
return INSTANCE;
}
}
懒汉式则在调用方法时才创建对象,故存在线程不安全的可能,使用synchronized同步锁来保证线程安全
class LazyBank{
private LazyBank(){
}
private volatile static LazyBank instance = null; //使用volatile关键字修饰,防止编译器重排序导致多线程情况下其他线程访问到未初始化的对象
private static LazyBank getInstance(){
if(instance == null){ //多一个判断,后续线程看到已经有实例了就不再进行初始化操作,直接返回结果,如果去掉仍可以保证单例,但这时每个线程试图获取实例都会进行synchronized操作,严重消耗性能。
synchronized (LazyBank.class) {
if(instance == null){ //该判断不可去掉,不然在并发情况下会出现某一线程正在创建实例,而另一个线程进来判断instance == null,同样创建实例,这就无法保证单例了。(CPU性能贼快,只要操作不是原子性的,存在一定的时间空隙,对它而言就有机会“插入”其它操作)
instance = new LazyBank();
}
}
}
return instance;
}
}
不使用volatile关键字修饰可能出现的重排序问题