当Singleton不是Singleton?

时间:2013-06-30 01:25:06

标签: java design-patterns singleton

我正在阅读blog,其中讨论了当Singleton不是Singleton时。

在其中一个作者尝试解释的案例中,显示了在Singleton上实现时双重检查锁定也是一个失败。

// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}

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

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

有人可以帮我解释这究竟是什么意思吗?

3 个答案:

答案 0 :(得分:4)

我会试着谈谈它。

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

现在,如果我们使用多个线程,如果对象已经存在,那么让我们返回它,因为方法会在内部与线程竞争条件同步。我们可以在进入同步块之前执行此操作,就好像它已创建一样,它已创建。构造函数已经设计好,因此无法返回部分构造的对象,如内存模型设计所指定的那样。

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

如果没有,让我们锁定并返回一个新的。通过握住锁,我们现在保护单身从另一侧。另一个线程等待锁定,并注意到它已被创建(根据内部空值比较)返回现有的。如果我们没有获得锁定,那么线程会对变化进行压缩,并且发现它们的变化也会被破坏。 请注意,您帖子中的代码块不完整。如果使用else块返回_instance任何空检查,则需要返回false

现在,如果我们处于 - 线程环境中,这一点就不重要了。我们可以使用:

public static MySingleton getInstance() {
    if (_instance==null) {
        _instance = new MySingleton();
    }
    else return _instance;
}

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

您仍然应该在自己的类中自己实现这一点以确保线程安全。

答案 1 :(得分:3)

没有解释它在报价中如何失败。他只是解释双重检查锁定。他可能会在其他地方提到双重检查锁定本身在Java 1.5之前不起作用的事实。但那是很久以前的事了。

答案 2 :(得分:1)

我在维基百科上找到了对不同Singleton实现的最佳解释,它们的缺陷和最好的东西。请点击此链接:

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

希望它有所帮助!