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

Java双重检查锁定

东门清夷
2023-03-14
问题内容

我偶然遇到了一篇文章,该文章最近讨论了Java中的双重检查锁定模式及其陷阱,现在我想知道我多年来使用的那种模式的变体是否会遇到任何问题。

我看过许多关于该主题的文章和文章,并了解了对部分构造的对象的引用所带来的潜在问题,据我所知,我认为我的实现不受这些问题的影响。以下模式是否有问题?

而且,如果没有,人们为什么不使用它?在围绕此问题进行的任何讨论中,我从未见过推荐它的方法。

public class Test {
    private static Test instance;
    private static boolean initialized = false;

    public static Test getInstance() {
        if (!initialized) {
            synchronized (Test.class) {
                if (!initialized) {
                    instance = new Test();
                    initialized = true;
                }
            }
        }
        return instance;
    }
}

问题答案:

双重检查锁定已损坏。由于初始化是原语,因此它可能不需要易失性即可工作,但是在实例初始化之前,没有什么可以阻止初始化被视为对非同步代码是正确的。

编辑:为了澄清上述答案,原始问题询问有关使用布尔值来控制双重检查锁定的问题。如果没有以上链接中的解决方案,它将无法正常工作。你可以仔细检查锁定,实际上是设置一个布尔值,但是在创建类实例时,仍然存在有关指令重新排序的问题。建议的解决方案不起作用,因为在非同步块中看到初始化的布尔值为true后,实例可能未初始化。

仔细检查锁定的正确解决方案是使用volatile(在实例字段上)而忽略初始化的布尔值,并确保使用JDK 1.5或更高版本,或者在最终字段中对其进行初始化(如链接中所述)文章和汤姆的答案,或者只是不使用它。

当然,整个概念似乎是一个巨大的过早优化,除非你知道在获取此Singleton时将引起大量线程争用,或者你已对应用程序进行了概要分析并将其视为热点。



 类似资料:
  • 我使用Java大约一个月了,在编程方面仍然是一个一般的业余爱好者,所以如果我有什么不对的地方,请随时纠正我。也许我会提供一些多余的细节,但我现在是如此困惑,我无法决定什么是重要的。 所以,我一直在开发多线程客户机-服务器应用程序。所有线程都在使用同一个对象,其中存储了某些配置值和共享记录器;此对象在server-thread中初始化,然后作为参数传递给client-thread类构造函数。首先,假

  • 问题内容: 此问题与旧Java版本的行为以及双重检查锁定算法的旧实现有关 较新的实现使用volatile并依赖于略有更改的语义,因此它们 不会 损坏。 声明字段分配始终是原子的,除了long或double字段。 但是,当我阅读解释为什么双重检查锁定被破坏时,据说问题出在赋值操作中: 线程A注意到该值未初始化,因此它获得了锁并开始初始化该值。 由于某些编程语言的语义,允许编译器生成的代码在A完成执行

  • 这是我为单例模式的自定义类。在这段代码中,我使用双重检查锁定,如下所示。当我在一些源代码上读到许多帖子时,他们说双重检查很有用,因为它可以防止两个并发线程同时运行,从而产生两个不同的对象。 我还是不太懂上面的代码。当实例为null时,如果两个线程一起运行同一行代码,问题是什么? 当它出现时。两个线程都将看到对象为null。然后两者同步。然后,他们再次检查,仍然看到它为空。并创建两个不同的对象。哎呀

  • 据我所知,这是Java中双重检查锁定模式的正确实现(自Java5): 我想知道缺少是一个严重的错误,还是一个可能存在性能缺陷的轻微缺陷,假设只能通过访问。 我的想法是这样的:引入了事前发生关系。初始化的线程将其值写入离开同步块的主存储器。因此,即使不是易失性的,也不会有的双重初始化:其他线程的本地副本中有(在第一次检查中得到),但是必须在进入同步块后的第二次检查中从主存储器中读取新值(get并且不

  • 本文向大家介绍双重检查加锁单例 线程安全-Java版相关面试题,主要包含被问及双重检查加锁单例 线程安全-Java版时的应答技巧和注意事项,需要的朋友参考一下 双重检验加锁模式(double checked locking pattern),是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查 ,一次是在同步块外,一次是在同步块内。为什么在同步块内还要再检验一次?因为可能会有多个线

  • 本文向大家介绍Java双重检查加锁单例模式的详解,包括了Java双重检查加锁单例模式的详解的使用技巧和注意事项,需要的朋友参考一下 什么是DCL DCL(Double-checked locking)被设计成支持延迟加载,当一个对象直到真正需要时才实例化: 为什么需要推迟初始化?可能创建对象是一个昂贵的操作,有时在已知的运行中可能根本就不会去调用它,这种情况下能避免创建一个不需要的对象。延迟初始化