2013-03-20 64 views
5

使用双重检查锁定习惯用于单例模式会更好吗?或者一个同步的方法?使用双重检查锁定习惯用于单身模式是否最佳?

即:

private static volatile ProcessManager singleton = null; 

public static ProcessManager getInstance() throws Exception { 

    if (singleton == null) { 
     synchronized (MyClass.class) { 
      if (singleton == null) { 
       singleton = new ProcessManager(); 
     } 
     } 
    } 
    return singleton; 

}

private static processManager singleton = null; 

public synchronized static processManager getInsatnce() throws Exception { 

    if(singleton == null) { 
      singleton = new processManager(); 
    } 

    return singleton 
} 
+0

有两个嵌套IFS没有任何东西之间,就像在你的第二段代码中一样,没有任何意义。 – Jesper 2013-03-20 14:52:14

+4

以上都不是,如[本答案](http://stackoverflow.com/a/15498689/1103872)中对您自己以前的问题所述。 – 2013-03-20 14:52:41

+0

在你的第二个例子中,由于你已经在关键部分 – Grimmy 2013-03-20 14:54:52

回答

0

基本上,你的第二个选项添加没有额外的保障。

您经常检查,但它们之间仍可能发生并发访问,因此,您正在减少发生两个实例的可能性,但不会消除它。

6

有ClassLoader的为你做的工作:

/* 
    * This solution takes advantage of the Java memory model's guarantees about class initialization 
    * to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it 
    * is needed. That means that the first time getInstance is called, mySingletonServiceLoader 
    * will be loaded and instance will be created, and since this is controlled by ClassLoaders, 
    * no additional synchronization is necessary. 
    */ 
    public static DocumentService getInstance() { 
     return mySingletonServiceLoader.INSTANCE; 
    } 

    private static class mySingletonServiceLoader { 
     static DocumentService INSTANCE = new DocumentService(); 
    } 
} 
0

第一个选项。

有创建单一实例的多个版本的能力...

getInstance()调用的实例检查null,然后立即构造,如果它为空,然后instance返回。

它应该是线程安全的。

也请参考this也。

0

第一个选项是正确的双重检查锁定的实现,但如果在ProcessManager的类,但的getInstance没有更多的公共方法,那么所有你需要的是

public class ProcessManager { 
    private static ProcessManager instance; 
    static { 
     instance = new ProcessManager(); 
    } 

    private ProcessManager() { 
    } 

    public static ProcessManager getInstance() { 
     return instance; 
    } 
} 

类将被加载并在第一ProcessManager的初始化.getInstance()调用

0

如果需要延迟加载,我会坚持双重检查而不是同步方法。最后,问题是,volatile vs. synchronized

挥发性,简单地让所有的访问(读取或写入)到volatile变量发生到主内存,有效地把挥发性可变出CPU缓存。这对于一些只需要变量可见性正确且访问顺序不重要的操作而言可能很重要。

一旦实例被初始化,同步块将不会被执行(但是竞争条件)。要支付的唯一并发成本是对易失性变量的单次读取。

注意,在有效的Java布洛赫说,在一个局部变量加载挥发性场增强性能(据我所知,是因为有较少的挥发性读取)

public static ProcessManager getInstance() throws Exception { 
    ProcessManager result = singleton; 
    if (result == null) { 
    synchronized (MyClass.class) { 
     result = singleton; 
     if (result == null) { 
      singleton = result = new ProcessManager();    
     } 
    } 
    return result; 
} 
相关问题