[Java] [Singleton] [DCL]

來源:互聯網
上載者:User

標籤:懶漢   指令重排序   意思   single   操作   自己的   原子操作   col   可見度   

Singleton
  • 只能有一個執行個體;必須自己建立自己的執行個體;必須給其他所有對象提供這一執行個體
實現方法餓漢式singleton
  • 積極式載入法
  • class Single {  private Single() {    System.out.println("ok");  }    private static Single instance = new Single();    public static Single getInstance() {    return instance;  }}
  • 優點:
    • thread safe
    • 調用時速度快(在類載入時已經建立好一個static對象)
  • 缺點:
    • 資源使用率不高(可能系統不需要)
    • 在一些情境下無法使用。比如在single執行個體的建立依賴參數或設定檔時。
懶漢式singleton
  • 消極式載入法
  • public class LazySingleton {  private static LazySingleton instance;  private LazySingleton() {}    public static LazySingleton getInstance() {    if (instance == null) {      instance = new LazySingleton();    }    return instance;  }}
  • 適用於單線程環境,not trhead-safe,getInstance()方法可能返回兩個不同執行個體。
  • 可以改成thread-safe版本,如下:
    public class LazySingleton {    private static LazySingleton instance;        private LazySingleton() {}        public static synchronized LazySingleton getInstance() {             if (instance == null) {                       instance = new LazySingleton();           }        return instance;                                          }}
  • 優點:不執行getInstance對不會被執行個體化
  • 缺點:第一次載入時反應不快。每次調用getInstance的同步開銷大。(大量不必要的同步)
DCL singleton
  • Double Check Lock
  • 避免每次調用getInstance方法時都同步
  • public class LazySingleton {  private static LazySingleton instance;  private LazySingleton() {}    public static LazySingleton getInstance() {    if (instance == null) {      synchronized(LazySingleton.class) {        if (instance == null) {          instance = new LazySingleton();        }      }    }    return instance;  }}
  • 第一層判斷,避免不必要的同步。第二層判斷則是線上程安全的情況下建立執行個體。
  • 優點:資源使用率高,多線程下效率高。
  • 缺點:第一次載入時反應不快,由於java記憶體模型一些原因偶爾會失敗,在高並發下有一定的缺陷。
  • 上述代碼依然存在不安全性:
    instance = new LazySingleton()這條語句實際上不是一個原子操作,它大概包括三件事:
    1. 給LazySingleton的執行個體分配記憶體;
    2. 初始化LazySingleton()的構造器;
    3. 將instance對象指向分配的記憶體空間(在這一步的時候instance變成非null)。

  但是由於Java編譯器允許處理器亂序執行(指令重排序),上述2、3點的順序是無法保證的。(意思是可能instance != null時有可能還未真正初始化構造器)。 
  解決方案是通過將instance定義為volatile的。(volatile有兩個語義:1. 保證變數的可見度;2. 禁止對該變數的指令重排序)

  • 參考<<Java並發編程>> P286 ~ P287。在JMM後續版本(>= Java5.0)中,可以通過結合volatile的方式來啟動DCL,並且該方式對效能的影響很小。然而,DCL的這種使用方式已經被廣泛地拋棄了。
  • (因為volatile屏蔽指令重排序的語義在JDK1.5中才被完全修複,此前的JDK中即使將變數聲明為volatile,也仍然不能完全避免重排序所導致的問題,這主要是因為volatile變數前後的代碼仍然存在重排序問題。)
static內部類singleton
  • class Single {  private Single() {}    private static class InstanceHolder {    private static final Single instance = new Single();  }    public static Single getInstance() {    return InstanceHolder.instance();  }}
  • 優點:安全執行緒,資源使用率高。
  • 缺點:第一次載入時反應不快。
  • 原理:類級內部類(static修飾的成員內部類)只有在第一次使用時才會被載入。
Summary
  • 考慮到效率、安全性等問題,一般常用餓漢式singleton or static內部類singleton。其中後者是常用的singleton實現方法。

 

[Java] [Singleton] [DCL]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.