Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么时候单身不是单身?_Java_Design Patterns_Singleton - Fatal编程技术网

Java 什么时候单身不是单身?

Java 什么时候单身不是单身?,java,design-patterns,singleton,Java,Design Patterns,Singleton,我在读一篇关于什么时候单身不是单身的文章 // Double-checked locking -- don't use public static MySingleton getInstance() { if (_instance==null) { synchronized (MySingleton.class) { if (_instance==null) { _instance = new MySingleton();

我在读一篇关于什么时候单身不是单身的文章

// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}
在作者试图解释的其中一个案例中,我们可以看到,当在Singleton上实现双重检查锁定时,双重检查锁定是如何失败的

// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}
对于上述代码块,作者说:

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


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

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

我在维基百科上找到了对不同的单例实现、它们的缺陷以及什么是最好的解释。请点击此链接:


希望有帮助

我会试着把它讲清楚

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

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

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

如果没有,让我们锁定它并返回一个新的。通过持有锁,我们现在可以从另一边保护singleton。另一个线程等待锁,并注意到它已被创建(根据内部空比较)返回现有的锁。如果我们没有获得锁,线程将对更改进行滚动,并发现它们的更改也被破坏。 请注意,您文章中的代码块不完整。如果任何空检查返回了
false
,则需要使用else块返回
\u实例

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

public static MySingleton getInstance() {
    if (_instance==null) {
        _instance = new MySingleton();
    }
    else return _instance;
}
对于较新的版本,java在许多情况下使用这种行为,作为其库的一部分,在花时间获取锁之前检查是否需要锁。在此之前,它要么未能获得锁(坏,数据丢失),要么立即获得锁(坏,更可能出现减速和死锁)


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

相关且更具启发性的是:这意味着这是错误的代码,因为它从不从(据称)值返回函数返回值。同步(MySingleton.class)将如何确保这一点?我觉得整个方法都必须同步。@Sam如果它不是空的,设计保证它在任何情况下都不会被更改为空(因为该方法从来没有一行可以这样做),因此如果它是空的,那么我们将获得锁,因为只有这样我们才能进行更改。根据您的解释“对于较新版本,java在许多情况下都会使用这种行为,在花时间获取锁之前检查是否需要锁”。您的意思是,在较新版本的java中,不需要执行这种双重锁定吗?@Sam No,在构建自己的类时需要双重锁定。java的内部类使用它,以在不牺牲数据完整性的情况下获得更高的性能。