不使用synchronized和lock,如何实现线程安全的单例?最常回答的是静态内部类和枚举。好吧,这两个确实是可以实现的。枚举publicnumSingleton{INSTANCE;publicvoidwhateverMethod(){}}静态内部类很好,这也是真的publicstaticfinalSingletongetInstance(){returnSingletonHolder.INSTANCE;}}(更多单例实现方法参见:单例模式的七种写法)问:这些单例实现方法的真正原理是什么?答:以上实现方式均使用了ClassLoader的线程安全机制。先解释清楚为什么要用ClassLoader。从后往前,先来说说这两个饿汉。实际上,它们都定义了静态成员变量,以保证在类初始化时可以实例化实例。那为什么要让实例在类初始化的时候实例化才能保证线程安全呢?因为类的初始化是通过ClassLoader来完成的,这实际上是在利用ClassLoader的线程安全机制。除了静态内部类之外,这个方法与两个饿方法只有一点点不同,但是方法稍微优雅一些??。这样就加载了Singleton类,不一定要初始化实例。因为没有主动使用SingletonHolder类,所以只有在调用getInstance方法实例化实例时才会显示和加载SingletonHolder类。..不过原理和饿汉是一样的。***说到枚举,其实如果你反序列化枚举类,你会发现他也是用staticfinal来修饰每一个枚举项。(详见:深入剖析Java的枚举类型--枚举的线程安全与序列化问题)至此,我们已经明确了所有读者的答案都使用了ClassLoader的线程安全机制。至于为什么ClassLoader加载类是线程安全的,可以在这里直接回答:ClassLoader的loadClass方法在加载类时使用了synchronized关键字。因此,除非被重写,否则此方法在整个加载过程中默认是同步的(线程安全的)。(详见:深入剖析Java的ClassLoader机制(源码级))哈哈哈哈!!!~所以,到这里可以说大家的回答只对了一半。虽然没有展示synchronized和lock的使用,但还是间接使用了!!!!那么,这里又有一个问题:如何在不使用synchronized和lock的情况下实现线程安全的单例?【本文为专栏作家霍利斯原创文章,作者微信公众号Hollis(ID:hollishuang)】点此阅读更多本作者好文
