1、synchronized虽然能保证synchronized中的代码能够在某个线程中执行完,再被其他线程访问,但是不能保证synchronized中的代码在执行时,其他线程访问单例对象。如果单例对象的创建发生指令重排,即使加了synchronized,那么在重排过程中,对单例对象的访问还是线程不安全的。
2、一旦我们加上volitate,避免了指令重排,那么就等于保证了在synchronized过程中,其他线程对单例对象的访问时,要么是null,要么就是初始化完成的对象。而不会说先拿到未初始化的对象,后又拿到已经初始化的对象。
public class Singleton {
private volatile static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {//避免指令重排后,这里访问单例对象要么是null继续等锁释放。要么就是初始化完成的对象return。
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}