Java DCL(Double Check Lock)單例模式詳解

單例模式是應用最廣的模式之一。相信大家都非常熟悉了,什么,不熟悉?你都單例模式單刷了二十年了,還不懂?好吧,不懂的同學請自行百度。

首先是最經典的癡漢...不是,餓漢模式:

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf=new Girlfiriend ();
  private Girlfiriend (){
  }
  public static Girlfiriend getGirlfriend(){
        return gf;  
}
}

餓漢模式什么都好,就是有點占地方,每次加載類的時候就存在了。有沒有什么辦法,用的時候在加載呢。沒辦法,世界是被懶人推動前進的,還真有。

懶漢模式:

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf;
  private Girlfiriend (){
  }
  public static synchronized Girlfiriend getGirlfriend(){
     if(gf==null){
        gf= new Girlfriend();
      }
        return gf;  
}
}

這種方法實現了在需要的時候加載。但是注意這里的synchronized關鍵字,synchronized 保證了當進行多線程操作的時候不會產生多個實例。但是這種做法有一個缺點,不管是不是已經存在實例了,都會被鎖阻塞。
那么,有沒有什么辦法解決呢。這個世界是由聰明人改善,所以當然有!

當當當當,DCL模式來了。DCL是不是聽起來特別高大上,其實就是Double Check Lock,說人話就是,你瞅兩次看看到底有沒。

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf;
  private Girlfiriend (){
  }
  public static  Girlfiriend getGirlfriend(){
     if(gf==null){
        synchronized(Girlfriend.class){
            if(gf==null){
              gf= new Girlfriend();
            }
        }
      }
        return gf;  
}
}

是不是感覺這就結束了。一篇好的文章是要出其不意的。所以,沒完。
DCL并不是十分穩定的,由于java編譯器允許處理器亂序執行,所以這樣做是有隱患的。
簡單說,其實new對象的操作不是原子性的。這句代碼最終會被編譯成多條匯編指令。
(1)給Girlfriend的實例分配內存
(2)調用Girlfriend()的構造函數,初始化成員字段
(3)將gf對象指向分配的內存空間
也就是說這三條指令順序是不可預知的。當另一個線程執行第一個if(gf==null)的時候,由于已經調用了構造函數,但是構造還沒有完成。會把沒有構造完全的對象返回。
那么怎么解決呢,聰明的你一定也能想到,只不過聰明人太多,有人先想到了:
靜態內部類單例模式:

public class Girlfiriend extends Friend{
  private Girlfiriend (){
  }
  public static Girlfiriend getGirlfriend(){
        return GirlfriendMother.gf;  
}
private static class GirlfriendMother{
        private static final Girlfiriend gf= new Girlfiriend ();
}
}

第一次加載Girlfriend的時候,gf不會被初始化,(java類只有被調用的時候才會初始化)。這種方式不僅能夠確保線程的安全,也能夠保證單例對象的唯一性,同時也延遲了單例的實例化。所以這才是推薦使用的單例模式實現的方式。

嘿嘿,你以為到這就完了?too young too naive:
最后是一種單例模式的終極形態——枚舉單例:

public enum Girlfriend{
GIRLFRIEND;
}

默認枚舉實例的創建是線程安全的,并且在任何情況下它都是一個單例。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 單例模式(SingletonPattern)一般被認為是最簡單、最易理解的設計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,292評論 4 34
  • 前言 本文主要參考 那些年,我們一起寫過的“單例模式”。 何為單例模式? 顧名思義,單例模式就是保證一個類僅有一個...
    tandeneck閱讀 2,538評論 1 8
  • 一.什么是單例模式 單例模式的定義:確保一個類只有一個實例,并提供一個訪問他的全局訪問點。單例模式是幾個設計模式中...
    Geeks_Liu閱讀 2,244評論 0 10
  • 1.單例模式概述 (1)引言 單例模式是應用最廣的模式之一,也是23種設計模式中最基本的一個。本文旨在總結通過Ja...
    曹豐斌閱讀 3,005評論 6 47
  • 生活是用來熱愛的,不是用來等待的。過好每個瞬間,也就能過好這一生。 懂很多道理,不如珍惜生命的中的小確幸,小確幸積...
    小李非刀閱讀 6,402評論 69 180