Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/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,可能重复: 我本以为下面的类是线程安全的单例,但读起来似乎不是 public class ThreadSafeSingleton { private static ThreadSafeSingleton ref; private ThreadSafeSingleton(){ } public ThreadSafeSingleton getSingletonObject(){ if(ref == null){ re

可能重复:

我本以为下面的类是线程安全的单例,但读起来似乎不是

public class ThreadSafeSingleton {

    private static ThreadSafeSingleton ref;

    private ThreadSafeSingleton(){

    }

    public ThreadSafeSingleton getSingletonObject(){

        if(ref == null){
            ref = new ThreadSafeSingleton();
        }   
        return ref;

    }
}
根据文章,唯一真正线程安全的单例是——

public class ThreadSafeSingleton {

    private static ThreadSafeSingleton ref = new ThreadSafeSingleton();

    private ThreadSafeSingleton(){

    }

    public ThreadSafeSingleton getSingletonObject(){
        return ref;

    }
}

这是否正确?

这不是唯一的线程安全单例,但这是正确的。另一种方法是同步第一个示例中创建singleton实例的代码。但问题是您必须同步代码,这可能是问题,也可能不是问题。另一个可能的问题是单例没有延迟初始化。同样,这可能是问题,也可能不是问题,这取决于体系结构和需求。还有另一种处理这个问题的奇怪模式:。

这不是唯一的线程安全单例,但这是正确的。另一种方法是同步第一个示例中创建singleton实例的代码。但问题是您必须同步代码,这可能是问题,也可能不是问题。另一个可能的问题是单例没有延迟初始化。同样,这可能是问题,也可能不是问题,这取决于体系结构和需求。还有另一种处理这个问题的奇怪模式:

如果(ref==null),两个大致同时运行的线程可能会命中
。两个线程可以看到
ref
实际上是空的。然后,两个线程将创建一个新实例。然后可以给两个线程提供单独的实例。现在您有了两个不同的“singleton”对象实例

此代码段中没有防止上述竞争条件的机制

如果(ref==null)
,两个大致同时运行的线程可能会命中
。两个线程可以看到
ref
实际上是空的。然后,两个线程将创建一个新实例。然后可以给两个线程提供单独的实例。现在您有了两个不同的“singleton”对象实例

此代码段中没有防止上述竞争条件的机制。

是的,它是正确的

在第一种情况下,如果两个线程同时调用
getSingletonObject()
,则有可能最终得到两个singleton实例

在第二种情况下,该方法只返回对类加载期间创建的现有对象的引用,这是由JVM以线程安全的方式完成的

就线程安全性而言,第二种方法比第一种方法好得多。

是的,它是正确的

在第一种情况下,如果两个线程同时调用
getSingletonObject()
,则有可能最终得到两个singleton实例

在第二种情况下,该方法只返回对类加载期间创建的现有对象的引用,这是由JVM以线程安全的方式完成的


就线程安全性而言,第二种方法要比第一种方法好得多。

是的,本文是正确的

在上面的示例中,如果该方法同时被两个函数调用,它们可能都会将
ref
视为null,因为在另一个函数检查它之前,两个函数都没有完成创建和赋值


在下面的示例中,
ref
在类加载时分配一次,然后任何东西都可以访问它。

是的,本文是正确的

在上面的示例中,如果该方法同时被两个函数调用,它们可能都会将
ref
视为null,因为在另一个函数检查它之前,两个函数都没有完成创建和赋值


在下面的示例中,
ref
在类加载时分配一次,然后任何东西都可以访问它。

有两种不同的方法来实现线程安全的单例对象。静态初始化(底层方法)就是其中之一

您还可以使用,synchronize
getInstance()
,甚至可以使用,只要holder变量声明为volatile
。有关更多信息,请参阅


其中,如果我必须构建一个实际的单例,我更喜欢第一种方法。否则,我喜欢在中使用作用域

有两种不同的方法来实现线程安全的单例对象。静态初始化(底层方法)就是其中之一

您还可以使用,synchronize
getInstance()
,甚至可以使用,只要holder变量声明为volatile。有关更多信息,请参阅


其中,如果我必须构建一个实际的单例,我更喜欢第一种方法。否则,我喜欢在中使用作用域

请检查右侧栏中的“相关”列表(顺便说一下,它与您键入问题标题后显示的列表完全相同)。当然,这个问题以前被问过无数次:)肯定不是唯一的线程安全方式,甚至不是最好的线程安全方式。确实,顶部不是线程安全的,而底部似乎是线程安全的。我的理解是,底部解决方案是“最佳”线程安全的单例实现(尽管最佳方案可能取决于特定的用例)。Glowcoder,你推荐哪种方式更好?@increment如何定义“最佳”?不同的解决方案有不同的权衡。如果您以后只需要对象,那么它当然不是昂贵初始化的最佳方法。@user470184,这不是实现线程安全单例的唯一方法。博客上没有这么说。有许多特定于平台的解决方案,这些解决方案将在博客文章的末尾简要介绍。特别是,如果您使用的是J2SE 5.0或更高版本,那么您可以将
volatile
与DCLP一起使用,因此也可以进行延迟初始化。请检查右侧栏中的“相关”列表(顺便说一句,该列表与您键入问题标题后显示的列表完全相同)。这个问题肯定已经被问过无数次了
if(ref == null)
{
    ref = new ThreadSafeSingleton();
}            

return ref;