当前位置: 首页 > 知识库问答 >
问题:

单例双检查锁定

东方建修
2023-03-14

这是我为单例模式的自定义类。在这段代码中,我使用双重检查锁定,如下所示。当我在一些源代码上读到许多帖子时,他们说双重检查很有用,因为它可以防止两个并发线程同时运行,从而产生两个不同的对象。

public class DoubleCheckLocking {

    public static class SearchBox {
        private static volatile SearchBox searchBox;

        // private constructor
        private SearchBox() {}

        // static method to get instance
        public static SearchBox getInstance() {
            if (searchBox == null) { // first time lock
                synchronized (SearchBox.class) {
                    if (searchBox == null) {  // second time lock
                        searchBox = new SearchBox();
                    }
                }
            }
            return searchBox;
        }
}

我还是不太懂上面的代码。当实例为null时,如果两个线程一起运行同一行代码,问题是什么?

if (searchBox == null) {
                synchronized (SearchBox.class) {
                    if (searchBox == null) {
                        searchBox = new SearchBox();
                    }
                }
            }

当它出现时。两个线程都将看到对象为null。然后两者同步。然后,他们再次检查,仍然看到它为空。并创建两个不同的对象。哎呀。

请给我解释一下。我理解错了什么?

谢谢:)

共有3个答案

乜栋
2023-03-14

只有当您担心许多线程同时调用单例时,或者担心获取锁的成本时,这种双重检查锁才是必要的。

它的目的是防止不必要的同步,从而使代码在多线程环境中保持快速。

查看此链接了解更多信息。

如果您运行的Java为1.5或更高,并且您在双重检查锁定机制中使用了易失性关键字,它将正常工作。当您使用易失性关键字时,您的示例不会根据上面的相同链接中断。

许博达
2023-03-14

让我们看看这段代码:

1 if (searchBox == null) {
2     synchronized (SearchBox.class) {
3     if (searchBox == null) {
4         searchBox = new SearchBox();
5     }
6 }

让我们试着解释一下。假设我们有两个线程AB,假设其中至少有一个到达第3行并观察到searchBox==nulltrue。由于synchronized块,两个线程不能同时位于第3行。这是理解双重检查锁定为何有效的关键。因此,必须是AB先通过synchronized。在不丧失一般性的情况下,假设该线程是A。然后,当看到searchBox==null为true时,它将进入语句体,并将searchBox设置为searchBox的新实例。然后,它将最终退出同步块。现在轮到B进入:记住,B被阻止,等待A退出。现在,当它进入块时,它将观察搜索框。但是A将刚刚将searchBox设置为非null值就离开了。完成。

顺便说一下,在Java中,实现单例的最佳方法是使用单个元素enumtype。来自有效Java:

虽然这种方法还没有被广泛采用,但单元素枚举类型是实现单例的最佳方式。

萧晔
2023-03-14

否,因为您正在获取SearchBox.class的锁,所以一次只有一个线程将进入同步块。所以第一个线程进入,然后发现search chBox为空,并创建它,然后离开同步块,然后第二个线程进入块,然后发现search chBox不是空的,因为第一个线程已经创建了它它不会创建search chBox的新实例。

双重检查模式用于避免每次执行代码时获得锁。如果调用没有同时发生,那么第一个条件将失败,代码执行将不会执行锁定,从而节省资源。

 类似资料:
  • 问题内容: 我偶然遇到了一篇文章,该文章最近讨论了Java中的双重检查锁定模式及其陷阱,现在我想知道我多年来使用的那种模式的变体是否会遇到任何问题。 我看过许多关于该主题的文章和文章,并了解了对部分构造的对象的引用所带来的潜在问题,据我所知,我认为我的实现不受这些问题的影响。以下模式是否有问题? 而且,如果没有,人们为什么不使用它?在围绕此问题进行的任何讨论中,我从未见过推荐它的方法。 问题答案:

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

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

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

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

  • 编译器显示下一个错误:在这里输入图像描述