您的
getSingleton()方法正在尝试延迟初始化
SINGLETON实例,但存在以下问题:
- 不能访问变量
synchronized
- 变量不是
volatile
- 您没有使用双重检查锁定
因此竞争条件AMY会导致创建两个实例。
最好和最简单的方法是安全地懒惰地初始化一个单例 而不 同步,如下所示:
private static class Holder { static Singleton instance = new Singleton();}public static Singleton getSingleton() { // Note: "synchronized" not needed return Holder.instance;}这是线程安全的,因为java类加载器的约定是所有类在使用之前都必须完成其静态初始化。同样,类加载器在被引用之前不会加载类。如果
getSingleton()同时调用两个线程,则
Holder该类仍将仅加载一次,因此
newSingleton()将仅执行一次。
这仍然是懒惰的,因为
Holder类是 只 从引用
getSingleton()的方法,所以
Holder在第一次呼叫时类只会被加载
getSingleton()而成。
不需要同步,因为此代码依赖于类加载器的内部同步,这是防弹的。
此代码模式是单例飞行的唯一方法。它是:
- 最快(无同步)
- 最安全(取决于工业强度等级的装载机安全性)
- 最干净的(最少的代码-双重检查的锁定很丑陋,并且它的功能很多行)
另一种类似的代码模式(既安全又快速)是在
enum单个实例中使用,但是我发现这样做很笨拙,目的并不明确。



