单例模式

从形式上来看,Singleton Pattern是所有模式中最简单的一种,但是细究起来并不像想象中那么简单。

 

    Singleton的实现有多种方式(见下表及文后所附代码示例)。最基本的是第一种实现,这种实现最大的问题就是不支持多线程。《Head First Design Pattern》第五章列举了三种支持多线程的单例模式实现方式(表中第二、三、四种),这三种实现方式在性能上有所差异。

 

    对于第四种双检锁(DCL)方式,文中特别注明“在Java1.4及更早版本中,许多JVM对volatile关键词的实现,会导致双重检查加锁的实效”;博文[3][4]中对这个问题进行了说明:可能出现instance被赋值,但instance指向的对象尚未初始化完成的情况,此时其他线程若读取instance,就会有问题。[4]中的原话如下: 
    “The problem with DCL is that code of fetching reference to constructed Singleton object does not require synchronization. 
Lets say that thread ‘a’ has entered synchronized block, made the instance not null but hasn’t executed the constructor yet. At this stage thread ‘b’ preempts thread ‘a’. Thread ‘b’ checks if the instance is not null, and since its not, it returns reference to a partially constructed Singleton object.” 
   从JDK 1.5开始,这个问题已经被解决,DCL方式可正常运行。

 

    《Effective Java》中作者又提及另两种实现方式:

      第五种 Class holder lazy initialization (见Item 71): 能达到DCL方式一样的功效,但实现更简单。Joshua没有明说,但是从书中他的话来看,对静态域使用延迟初始化(Singleton模式中正是这种情况),应使用这种方式而不是DCL方式。由于这种方式只适用于静态域的情况,DCL方式可在实例域需要延迟初始化时使用。 

      第六种 Enum singleon (见Item 3): Joshua认为虽然这种方式还没有被广泛采用,但这是实现Singleton的最佳方法(更简洁,自动支持序列化机制,绝对防止多次实例化)。

    

    在网上查找”Class holder lazy initialization ”时,发现已经有人总结过Singleton的这些实现方式[4],写的很清楚(有点小问题:该文介绍DCL方式时,指出了这种方式存在的问题,但未说明JDK1.5开始这个问题已经被解决)。综合这些资料,列了下面的一览表:


附各种实现方式的代码示例

第一种 (classic)


第二种 (use "synchronize" keyword)


第三种 (eagerly create )


第四种 (双检锁)


第五种(lazy initialization holder class)


第六种(Enum Singleton)




发布了50 篇原创文章 · 获赞 1 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章