当前位置: 首页 > 面试题库 >

Java中的线程安全单例

堵彬彬
2023-03-14
问题内容

有关Singletons的维基百科文章提到了一些用线程安全的方法来用Java实现结构。对于我的问题,让我们考虑具有冗长的初始化过程并且一次被多个线程访问的Singleton。

首先,这个未提及的方法是线程安全的吗?如果是的话,它在什么上进行同步?

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的文章
在理解单例模式时值得一读。



 类似资料:
  • 本文向大家介绍Java线程安全中的单例模式,包括了Java线程安全中的单例模式的使用技巧和注意事项,需要的朋友参考一下 此种写法利用了类加载器的加载原理,每个类只会被加载一次,这样单例对象在其内部静态类被加载的时候生成,而且此过程是线程安全的。     其中method()方法封装内部单例对象的私有方法,作为对外接口使用,这样就可以如下调用     另外一种方式为采用枚举来实现。 以上就是本文的全

  • 问题内容: 我写了下面的Singleton类。我不确定这是否是线程安全的单例类吗? 谁能帮我这个?我在上述Singleton课堂上的任何想法都会有很大帮助。 更新代码: 我正在尝试将波希米亚建议纳入我的代码中。这是更新的代码,我得到了- 谁能看一下,让我知道这次是否正确? 问题答案: 但是有一个简单的技巧,可以让你的代码是线程安全的实现,并不需要同步!它称为“ 按需初始化持有人”习惯用法,它看起来

  • 我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢

  • 本文向大家介绍枚举单例 线程安全-Java版相关面试题,主要包含被问及枚举单例 线程安全-Java版时的应答技巧和注意事项,需要的朋友参考一下 用枚举写单例实在太简单了!这也是它最大的优点。下面这段代码就是声明枚举实例的通常做法。 我们可以通过EasySingleton.INSTANCE来访问实例,这比调用getInstance()方法简单多了。创建枚举默认就是线程安全的,所以不需要担心doubl

  • 我在多线程环境中做的工作很少。所以,我需要知道below类的getInstance函数是否是线程安全的。这是单例类: 在getInstance函数(未注释)中,返回静态对象的引用。它需要线程安全机制吗? 在第二个getInstance(注释)中,如果singleObject为null,我们就创建对象。所以,它需要锁定机制,需要同步,对吧?

  • 问题内容: 经过一番认真的搜索后,我发现RandomAccessFile- class不是线程安全的。现在,我可以使用一个信号量来锁定所有读取和写入,但是我认为这样做的效果不是很好。从理论上讲,一次可以进行多次读取和一次写入。如何用Java做到这一点?有可能吗? 谢谢! 问题答案: 文件的部分锁定是一项复杂的业务,许多操作系统都避免这样做。但是,如果您坚持要这样做,一种方法是设计自己的锁定机制对象