Java中的线程安全单例

关于Singletons的维基百科文章提到了几种线程安全的方式来实现Java中的结构。 对于我的问题,让我们考虑具有冗长的初始化过程并且一次被许多线程共享的单例。

首先,这是未提及的方法是否是线程安全的,如果是这样,它在什么时候同步呢?

public class Singleton {
    private Singleton instance;

    private Singleton() {
        //lots of initialization code
    }

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

其次,为什么下面的实现线程安全并且懒惰初始化? 如果两个线程同时进入getInstance()方法,会发生什么?

public class Singleton {
    private Singleton() {
        //lots of initialization code
    }

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

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

最后,在第二个例子中,如果一个线程首先获取实例,另一个线程获取实例并在第一个线程完成构造函数之前试图对其执行操作,那该怎么办? 那么你会进入一个不安全的状态吗?


答案1: static synchronized方法使用类对象作为锁 - 即在这种情况下Singleton.class

答案2:Java语言,其中包括:

  • 在第一次访问/使用时加载类
  • 保证在允许访问类之前,所有静态初始化器都已完成
  • 这两个事实意味着内部静态类SingletonHolder在调用getInstance()方法之前不会被加载。 在那个时刻,在进行调用的线程被授予访问权限之前,该类的静态实例被实例化为类加载的一部分。

    这一切意味着我们有安全的懒加载, 并且不需要任何同步/锁定!

    这种模式是用于单身人士的模式。 它击败了其他模式,因为MyClass.getInstance()是单例的事实上的行业标准 - 每个使用它的人都会自动知道他们正在处理一个单例(使用代码,总是显而易见的),所以这个模式具有正确的API和引擎盖下的正确实施。

    btw Bill Pugh的文章在理解单例模式时值得一读。

    链接地址: http://www.djcxy.com/p/91821.html

    上一篇: Thread Safe Singletons in Java

    下一篇: Navigation toolbar extends vertically after returned from full screen video