【问题标题】:why is static inner class singleton thread safe [duplicate]为什么静态内部类单例线程安全[重复]
【发布时间】:2019-12-04 15:52:02
【问题描述】:

正如标题所说,为什么静态嵌套类单例是线程安全的?

public class Singleton {
    private static class SingletonHolder {
        public static Singleton instance;

        public static Singleton getInstance() {
            if (null == instance) {
                instance = new Singleton();
            }
        }
    }

    public static Singleton getInstance() {
        return SingletonHolder.getInstance();
    }
} 

【问题讨论】:

  • 首先,你的代码无法编译。
  • 首先,您要实现的目标不会是单例,因为您仍然可以制作“n”个此类的对象。
  • 之所以提到这个类不是单例并且能够创建多个实例可能是检查错误的空值检查。 if (null == instance) 需要改为 if(instance == null)。如果我错了,请纠正我。

标签: java


【解决方案1】:

您展示的代码在技术上不是线程安全的。这种狡猾的代码经常会被破坏。

代码应如下所示:

public class Singleton  {    
    private static class SingletonHolder {    
        public static final Singleton instance = new Singleton();
    }    

    public static Singleton getInstance() {    
        return SingletonHolder.instance;    
    }    
}

这里我们在一个静态初始化器(SingletonHolder)中进行赋值,任何以正确的 happens-before 关系访问它的线程都可以看到它。嵌套类并没有什么特别之处,它只是允许使用外部类而无需立即构造单例对象。几乎可以肯定,这完全毫无意义,但它似乎取悦了一些人。

与以往一样,[mutable] 单例是一个非常糟糕的主意。

【讨论】:

  • 您的代码无法编译。 SingletonHolder 没有getInstance() 方法
  • 不可变单例的意义何在?
  • @zhong.j.yu 好吧,从任何合理的定义来看,它都不是单例。单实例实现对于函子(例如Comparators)和可区分值很有用。
  • 一个函子或一打没有区别;单例函子只是性能优化,对应用逻辑没有意义。
  • @TomHawtin-tackline 你可以添加一个私有的 Singleton 构造函数private Singleton() {} 来完成这个例子。
【解决方案2】:

它是线程安全的,因为 JVM 处理延迟加载嵌套类。

但是,您发布的代码似乎没有正确使用此模式(您不应该进行空检查),我认为这实际上破坏了线程安全。这是一篇不错的文章,您可以在其中阅读有关此模式为何有效以及如何正确使用它的更多信息:

Initialization-on-demand holder idiom

【讨论】:

  • 操作的代码绝对不安全...
  • OP ninja 编辑了问题。原件与汤姆霍廷的回答一样
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 2015-03-24
  • 1970-01-01
相关资源
最近更新 更多