singleton模式四种线程安全的实现
1.描述:
????Singleton(單例)是設計模式的一種,為了保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
2.主要特點:?????
????1)單例類確保自己只有一個實例(構造函數私有:不被外部實例化,也不被繼承)。
????2)單例類必須自己創建自己的實例。
????3)單例類必須為其他對象提供唯一的實例。
3.單例模式的應用:
????資源管理器,回收站,打印機資源,線程池,緩存,配置信息類,管理類,控制類,門面類,代理類通常被設計為單例類
????如果程序有多個類加載器又同時使用單例模式就有可能多個單例并存就要找相應解決方法了
4.實現方法:
如果應用程序總是創建并使用單例實例或在創建和運行時開銷不大。
1).Eager initialization?餓漢式單例類(依賴jvm在加載類時創建唯一單例實例)
public class EagerSingleton { // jvm保證在任何線程訪問uniqueInstance靜態變量之前一定先創建了此實例 private static EagerSingleton uniqueInstance = new EagerSingleton(); // 私有的默認構造子,保證外界無法直接實例化 private EagerSingleton() { } // 提供全局訪問點獲取唯一的實例 public static EagerSingleton getInstance() { return uniqueInstance; } } 如果開銷比較大,希望用到時才創建就要考慮延遲實例化,或者Singleton的初始化需要某些外部資源(比如網絡或存儲設備),就要用后面的方法了.2)Lazy initialization?懶漢式單例類
3)"雙檢鎖"(Double-Checked Lock)盡量將"加鎖"推遲,只在需要時"加鎖"(僅適用于java 5.0 以上版本,volatile保證原子操作)?
happens-before:"什么什么一定在什么什么之前運行",也就是保證順序性.
現在的CPU有亂序執行的能力(也就是指令會亂序或并行運行,可以不按我們寫代碼的順序執行內存的存取過程),并且多個CPU之間的緩存也不保證實時同步,只有上面的happens-before所規定的情況下才保證順序性.
JVM能夠根據CPU的特性(CPU的多級緩存系統、多核處理器等)適當的重新排序機器指令,使機器指令更符合CPU的執行特點,最大限度的發揮機器的性能.
如果沒有volatile修飾符則可能出現一個線程t1的B操作和另一線程t2的C操作之間對instance的讀寫沒有happens-before,可能會造成的現象是t1的B操作還沒有完全構造成功,但t2的C已經看到instance為非空,這樣t2就直接返回了未完全構造的instance的引用,t2想對instance進行操作就會出問題.
????volatile 的功能:
1. 避免編譯器將變量緩存在寄存器里??
2. 避免編譯器調整代碼執行的順序
優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。
public class DoubleCheckedLockingSingleton { // java中使用雙重檢查鎖定機制,由于Java編譯器和JIT的優化的原因系統無法保證我們期望的執行次序。 // 在java5.0修改了內存模型,使用volatile聲明的變量可以強制屏蔽編譯器和JIT的優化工作 private volatile static DoubleCheckedLockingSingleton uniqueInstance; private DoubleCheckedLockingSingleton() { } public static DoubleCheckedLockingSingleton getInstance() { if (uniqueInstance == null) { synchronized (DoubleCheckedLockingSingleton.class) { if (uniqueInstance == null) { uniqueInstance = new DoubleCheckedLockingSingleton(); } } } return uniqueInstance; } } 4)Lazy initialization holder class 滿足所有 Double-Checked Locking 滿足的條件,并且沒有顯示的同步操作public class LazyInitHolderSingleton { private LazyInitHolderSingleton() { } private static class SingletonHolder { private static final LazyInitHolderSingleton INSTANCE = new LazyInitHolderSingleton(); } public static LazyInitHolderSingleton getInstance() { return SingletonHolder.INSTANCE; } } 根據jvm規范,當某對象第一次調用LazyInitHolderSingleton.getInstance()時,LazyInitHolderSingleton類被首次主動使用,jvm對其進行初始化(此時并不會調用LazyInitHolderSingleton()構造方法),然后LazyInitHolderSingleton調用getInstance()方法,該方法中,又首次主動使用了SingletonHolder類,所以要對SingletonHolder類進行初始化,初始化中,INSTANCE常量被賦值時才調用了?LazyInitHolderSingleton的構造方法LazyInitHolderSingleton(),完成了實例化并返回該實例。 當再有對象(也許是在別的線程中)再次調用LazyInitHolderSingleton.getInstance()時,因為已經初始化過了,不會再進行初始化步驟,所以直接返回INSTANCE常量即同一個LazyInitHolderSingleton實例。
總結
以上是生活随笔為你收集整理的singleton模式四种线程安全的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源镜像站点列表
- 下一篇: Senparc.Weixin.MP SD