Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.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
java5之前版本:单例模式:双重检查锁定与静态工厂方法_Java_Oop_Design Patterns - Fatal编程技术网

java5之前版本:单例模式:双重检查锁定与静态工厂方法

java5之前版本:单例模式:双重检查锁定与静态工厂方法,java,oop,design-patterns,Java,Oop,Design Patterns,前JSE5: public class Singleton { private static volatile Singleton sic; private Singleton() {} public static Singleton getInstance() { if (sic == null) { // Let's make it thread safe using 'synchronized' synchronized(Singleton.

前JSE5:

public class Singleton {
  private static volatile Singleton sic; 
  private Singleton() {}

  public static Singleton getInstance() {
    if (sic == null) {
      // Let's make it thread safe using 'synchronized'
      synchronized(Singleton.class) {
        if (sic == null) {
          sic = new Singleton();        
        }
      }
    }
    return sic;
  }
}
在Pre-JSE5中实现单例设计模式的以下两种方法之间有什么区别?在我看来,两者都只是懒散的加载

即使静态工厂方法不是延迟加载,还有什么区别

双重检查锁定方法:

public class Singleton {
  private static volatile Singleton sic; 
  private Singleton() {}

  public static Singleton getInstance() {
    if (sic == null) {
      // Let's make it thread safe using 'synchronized'
      synchronized(Singleton.class) {
        if (sic == null) {
          sic = new Singleton();        
        }
      }
    }
    return sic;
  }
}
静态工厂法

public class Singleton_StaticFactory {
  private static final Singleton_StaticFactory s = new Singleton_StaticFactory();
  private Singleton_StaticFactory() {}
  public static Singleton_StaticFactory getInstance() {
    return s;
  }
}
更新

Russell Zahniser在他的回答中解释了为什么静态工厂实现在“getInstance”方法之前访问其他静态方法(如果存在)时,会以不需要的方式提前加载单例。因此,与我上面所说的不同,两者在“惰性初始化”方面并不相同


我仍然想知道是否还有其他区别。

如果
Singleton\u StaticFactory
有任何其他静态方法(或静态字段或公共构造函数),那么调用它们将触发加载该类并初始化Singleton。因此,在这种情况下,两者并不完全相等;否则它们是。

如果
Singleton\u StaticFactory
有任何其他静态方法(或静态字段或公共构造函数),则调用它们将触发加载该类并初始化Singleton。因此,在这种情况下,两者并不完全相等;否则就是这样。

在Java 1.5之前,写入
volatile
字段和从同一字段读取字段之间没有Before Before。因此,假设thread-A调用
getInstance()
,看到
sic==null
,实例化一个新的
单例
,并将其分配给
sic
。稍后,线程B调用
getInstance()
,看到
sic!=null
并返回它,而不经过
synchronized
块。在这种情况下,在创建
sic
的线程A和读取它的线程B之间,不会发生在边之前。这意味着,除非
Singleton
是线程安全的,即使面对不安全的发布(大多数对象都不是),否则存在争用条件,并且代码不是线程安全的

此外,在没有安全发布的情况下,使对象线程安全的方法之一是标记其所有字段
final
。这确保了任何读取这些
最终
字段之一的对象都将看到其在构造函数末尾的状态(只要不将
泄漏到构造函数之外)。但这种保证本身只是在Java1.5中添加的。这意味着在Java1.5之前,在没有安全发布的情况下,实际上没有任何方法可以使对象安全,因此双重检查锁总是不安全的


当然,所有这些都只适用于单例具有状态的情况——否则,就不需要安全地发布线程了

在Java1.5之前,写入到
volatile
字段和读取同一字段之间没有Before-Before。因此,假设thread-A调用
getInstance()
,看到
sic==null
,实例化一个新的
单例
,并将其分配给
sic
。稍后,线程B调用
getInstance()
,看到
sic!=null
并返回它,而不经过
synchronized
块。在这种情况下,在创建
sic
的线程A和读取它的线程B之间,不会发生在边之前。这意味着,除非
Singleton
是线程安全的,即使面对不安全的发布(大多数对象都不是),否则存在争用条件,并且代码不是线程安全的

此外,在没有安全发布的情况下,使对象线程安全的方法之一是标记其所有字段
final
。这确保了任何读取这些
最终
字段之一的对象都将看到其在构造函数末尾的状态(只要不将
泄漏到构造函数之外)。但这种保证本身只是在Java1.5中添加的。这意味着在Java1.5之前,在没有安全发布的情况下,实际上没有任何方法可以使对象安全,因此双重检查锁总是不安全的


当然,所有这些都只适用于单例具有状态的情况——否则,就不需要安全地发布线程了

简单的回答是双重检查锁定在Java1.4中无法可靠地工作

或Java并发的实践,第16.2节


长长的答案是@yshavit所说的。:-)

简单的回答是双重检查锁定在Java1.4中无法可靠地工作

或Java并发的实践,第16.2节


长长的答案是@yshavit所说的。:-)

还在使用Java1.4吗?换个工作,除非他们给你很好的薪水。。。检查一下这个extensively@zhong.j.yu这个问题的措辞让我觉得这是一个学术或求职面试问题,因为在java5之前有一个特殊的区别。还是在Java1.4上?换个工作,除非他们给你很好的薪水。。。检查一下这个extensively@zhong.j.yu这个问题的措辞让我觉得这是一个学术或面试问题,因为在java5之前有一个特殊的区别。DCL(双重检查锁定)在编译器中有一个主要缺陷。+1。我同意Russel Zahniser关于为什么在访问singleton类中的其他静态方法时静态工厂实现不会延迟加载的评论。非常感谢。我仍然会等待其他评论/答案,看看是否还有其他区别。dmos是正确的——它们不是1.5之前的等价物,这是问题的一部分。具体来说,在1.4及以下版本中,
Singleton_StaticFactory
是线程安全的,而双重检查锁定则不是。DCL(双重检查锁定)在编译器中有一个主要缺陷。+1。我同意