標籤:懶漢 指令重排序 意思 single 操作 自己的 原子操作 col 可見度
Singleton
- 只能有一個執行個體;必須自己建立自己的執行個體;必須給其他所有對象提供這一執行個體
實現方法餓漢式singleton
懶漢式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
但是由於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
Summary
- 考慮到效率、安全性等問題,一般常用餓漢式singleton or static內部類singleton。其中後者是常用的singleton實現方法。
[Java] [Singleton] [DCL]