publicclassSingleton { privatestaticSingletoninstance=null; privateint field1, field2 ... publicstatic Singleton getInstance() { // This is incorrect: don't do it at home, kids! if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = newSingleton(); } } } return instance; } privateSingleton() { } }
但是这样真的是没有任何问题吗?然而并不是,原因是instance = new Singleton();这句话并不是原子操作,这个实例化过程其实可以分成三步:1、 开辟一块内存;2、生成Singleton实例并调用Singleton构造方法;3、将生成的实例地址指向instance。JVM存在指令重排优化,不能保证1–>2—>3的执行顺序,调用链可能是1–>3—>2,3完成的时候,有些field并没有完成初始化,此时若有其他线程进入,因为instance,所以就有可能访问到非法的field,如下图所示:
那如何解决这个问题呢?答案是加volatile关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicclassSingleton { privatestaticvolatileSingletoninstance=null; privateint field1, field2 ... publicstatic Singleton getInstance() { // This is incorrect: don't do it at home, kids! if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = newSingleton(); } } } return instance; } }