Java中的线程安全单例 [英] Thread Safe Singletons in Java

查看:110
本文介绍了Java中的线程安全单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于Singletons的维基百科文章提到了一些在Java中实现结构的线程安全方法。对于我的问题,让我们考虑具有冗长初始化过程并且同时被许多线程所占据的单身人士。

The wikipedia article on Singletons mentions a few thread safe ways to implement the structure in Java. For my questions, let's consider Singletons that have lengthy initialization procedures and are acccessed by many threads at once.

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

Firstly, is this unmentioned method thread-safe, and if so, what does it synchronize on?

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()方法会发生什么?

Secondly, why is the following implementation thread safe AND lazy in initialization? What exactly happens if two threads enter the getInstance() method at the same time?

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;
    }
}

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

Finally, in the second example, what if one thread gets an instance first and another thread gets an instance and tries to perform actions on it before the constructor has finished in the first thread? Can you get into an unsafe state then?

推荐答案

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

Answer 1: static synchronized methods use the class object as the lock - ie in this case Singleton.class.

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

Answer 2: The java language, among other things:


  • 在首次访问/使用时加载类

  • 保证在允许访问类之前,所有静态初始化程序都已完成

这两个事实意味着内部静态类<$在调用getInstance()方法之前,不会加载c $ c> SingletonHolder 。在那一刻,在调用的线程被赋予访问权限之前,该类的静态实例被实例化为类加载的一部分。

These two facts mean that that the inner static class SingletonHolder is not loaded until the getInstance() method is called. At that moment, and before the thread making the call is given access to it, the static instance of that class is instantiated as part of class loading.

这就意味着我们有安全的延迟加载,没有任何需要同步/锁定!

This all means we have safe lazy loading, and without any need for synchronization/locks!

此模式是 用于单身人士的模式。它击败了其他模式,因为 MyClass.getInstance()是单身人士的事实行业标准 - 每个使用它的人都知道他们正在处理单身人士(带代码,它总是好的很明显),所以这个模式有正确的API 正确的实现。

This pattern is the pattern to use for singletons. It beats other patterns because MyClass.getInstance() is the defacto industry standard for singletons - everyone who uses it automatically knows that they are dealing with a singleton (with code, it's always good to be obvious), so this pattern has the right API and the right implementation under the hood.

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

btw Bill Pugh's article is worth reading for completeness when understanding singleton patterns.

这篇关于Java中的线程安全单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆