2010-12-05 59 views
1

下面的片段是直线前进,Singleton模式

public MyClass getInstance() { 
    if(uniqueInstance == null) { 
     uniqueInstance = new MyClass(); 
    } 
    return uniqueInstance; 
} 

什么是以下一种呢?

public MyClass getInstance() { 
    if(uniqueInstance == null) { 
     synchronized(MyClass.class) { 
      uniqueInstance = new MyClass(); 
     } 
    } 
    return uniqueInstance; 
} 

回答

5

这是一个很差的尝试,以使其线程安全,以防止由至少两个线程同时进入if块造成的竞争条件。

更安全一点的方法是添加额外的空检查,也称为double-checked locking

public MyClass getInstance() { 
    if (uniqueInstance == null) { 
     synchronized(MyClass.class) { 
      if (uniqueInstance == null) { 
       uniqueInstance = new MyClass(); 
      } 
     } 
    } 
    return uniqueInstance; 
} 

但是,我通常更喜欢Just Create One pattern而不是Singleton。

+0

“更安全一点”...我不太确定:http://www.google.ca/search?q=double+checked+locking+is+broken – 2010-12-05 06:05:48

3

这是一个线程安全的保险。

从和javaworld文章here

同步的方法保证 是对方法的调用不能 中断。

主要的想法是,如果你没有在synchronized块是可能的2个线程调用的getInstance并重新初始化对象,从而可能丢失任何状态数据(如果你甚至应该有状态数据一个单身人士)

1

第二个做同样的事情,除了:如果您使用第一个,如果创建一个新的MyClass需要一定的时间,并且在此期间,其他人也会调用MyClass.getInstance() ?你可能会结束两个实例。第二个版本锁定实例化行,这样如果另一个类尝试同时调用,它将等到第一个完成。

3

恕我直言,你应该首先从最简单的选项开始。最简单的单例是带有一个条目的枚举。鉴于类是负载懒惰,这仍然会给你懒加载,除非直接引用类,这不容易发生意外。

enum Singleton { 
    INSTANCE; 
} 

为避免意外加载,您可以使用内部类。

class Singleton { 
    static class SingeltonHolder { 
     static final Singleton INSTANCE = new Singleton(); 
    } 
    public static Singleton getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

注意;这两个解决方案都不需要同步,因为它们使用类加载是线程安全的事实。

总之;有些情况下需要锁定,但不要使它比需要更复杂。