合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
同步的懒加载虽然是线程安全的,但是导致性能开销。因此产生了双重检查锁定。但双重检查锁定存在隐藏的问题。`instance = new Instance()`实际上会分为三步操作:1)分配对象的内存空间;2)初始化对象;3)设置instance指向刚分配的内存地址;由于指令重排序,2和3的顺序并不确定。在多线程的情况下,第一个线程执行了1,3,此时第二个线程判断instance不为null,但实际上操作2还没有执行,第二个线程就会获得一个还未初始化的对象,直接使用就会造成空指针。 解决方案是用volatile修饰instance,在JDK 1.5加强了volatile的语意之后,用volatile修饰instance就阻止了2和3的重排序,进而避免上述情况的发生。 另一种方式则是使用静态内部类: ~~~ public class Singleton { private static class InstanceHolder { public static Singleton instance = new Singleton(); } public static Singleton getInstance() { return InstanceHolder.instance; } } ~~~ 其原理是利用类初始化时会加上初始化锁确保类对象的唯一性。