首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当Singleton不是Singleton时?

当Singleton不是Singleton时?
EN

Stack Overflow用户
提问于 2013-06-30 09:25:06
回答 3查看 1.1K关注 0票数 2

我读了一篇blog,讨论了什么时候单例不是单例。

在作者试图解释的其中一种情况中,显示了双重检查锁定在Singleton上实现时也可能失败。

代码语言:javascript
复制
// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}

对于上面的代码块,作者说:

“在这种情况下,我们打算避免每次调用方法时获取单例类的锁的开销。只有当单例实例不存在时才会获取锁,然后再次检查实例的存在,以防另一个线程在当前线程之前的瞬间通过第一次检查。”

有人能帮我解释一下这到底是什么意思吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-30 09:28:45

我会试着把这件事说清楚。

synchronized块需要时间才能进入,因为它需要跨线程协调。如果需要,我们将尽量避免输入它。

现在,如果我们使用多个线程,如果对象已经存在,让我们只返回它,因为方法将在内部根据线程竞争条件进行同步。我们可以在进入同步块之前这样做,就好像它是被创建的,它是被创建的。构造函数已经设计好了,所以不能返回部分构造的对象,正如内存模型设计所指定的那样。

如果单例对象还不存在,我们需要创建一个。但是如果在我们检查的时候另一个线程创建了它呢?我们将使用synchronized来确保没有其他线程持有它。现在,一旦我们进入,我们再检查一次。如果单例是由另一个线程创建的,那么让我们返回它,因为它已经存在。如果我们不这样做,一个线程可以获得它的单例并对它做一些事情,而我们只是在它的变化和效果上压路机。

如果没有,让我们锁定它并返回一个新的。通过持有锁,我们现在可以从另一端保护单例。另一个线程等待锁,并注意到它已经被创建(根据内部null比较)返回现有的锁。如果我们没有获得锁,线程都会在更改上进行压路机操作,并且发现它们的更改也被销毁了。请注意,您帖子中的代码块是不完整的。如果任何null检查使用else块返回false,则需要返回_instance

现在,如果我们在单线程环境中,这就不重要了。我们可以只使用:

代码语言:javascript
复制
public static MySingleton getInstance() {
    if (_instance==null) {
        _instance = new MySingleton();
    }
    else return _instance;
}

在较新的版本中,java在许多情况下使用此行为,作为其库的一部分,在花费时间获取锁之前检查是否需要锁。以前,它要么无法获得锁(坏的,数据丢失),要么立即获得锁(坏的,更有可能减速和死锁)。

为了线程安全,您仍然应该在自己的类中实现它。

票数 4
EN

Stack Overflow用户

发布于 2013-06-30 09:28:23

他没有解释为什么它会在这句话中失败。他只是在解释双重检查锁定。他可能在其他地方提到了双重检查锁定本身在Java1.5之前不起作用的事实。但那是很久以前的事了。

票数 3
EN

Stack Overflow用户

发布于 2013-06-30 09:28:33

我在维基百科上找到了对不同的Singleton实现的最好的解释,它们的缺陷以及什么是最好的。请访问以下链接:

http://en.wikipedia.org/wiki/Singleton_pattern

希望它能帮上忙!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17386227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档