單例模式

從形式上來看,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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章