1、單例模式簡介數據庫
單例模式是爲保證一個對象,在程序運行的任什麼時候刻只有一個實例存在,咱們把這種實現方式稱之爲「單例模式」。安全
2、單例模式的核心函數
單例類只有一個實例存在性能
單例類提供一個全局訪問點測試
單例類經過本身建立惟一實例網站
單例類對外全部訪問對象都提供一個惟一實例。spa
3、單例模式的優勢線程
一、在程序運行中只有一個實例,減小內存佔用,減小頻繁的建立和銷燬實例所帶來的系統開銷,設計
二、避免資源的多種無效佔用日誌
單例模式缺點:
沒有接口 不能繼承
4、單例模式應用場景
當一個事物在特定的環境中,只會存在一個實例時,咱們能夠採用單例模式對其進行設計。
例: 數據庫鏈接池,計算機註冊表 一個國家只有一個總統 日誌系統中的日誌文件 計算機中的打印池 計算機設備管理器
生成惟一序列號 網站計數器
5、單例模式的實現方式
一、非線程安全(儘可能不要用)
public sealed class Singleton { private static Singleton instance=null; private Singleton() { } public static Singleton Instance { get { if (instance==null) { instance = new Singleton(); } return instance; } } }
說明:上面的方法是非線程安全的,2個不一樣的線程能夠同時進入這個方法,若是instance爲空的而且這裏返回真的狀況下,均可以建立實例,這顯然違反了單例模式,實際上,在測試之前,實例就已經有可能被建立了,
可是內存模型不能保證這個實例能被其餘的線程看到,除非合適的內存屏障已經被跨過了。
二、簡單的線程安全
public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { lock (padlock) { if (instance == null) { instance = new Singleton(); } return instance; } } } }
上述實現是線程安全的。這個線程在共享的object上取出了一把鎖,而後在建立實例之前檢查這個實例是否被建立了。
這個保護了內存屏障問題(lock保證了全部的讀取操做是在LOCK得到之後發生的,全部的unlock保證了全部的寫操做在lock 釋放之後發生的),這樣就保證了一個線程只能建立一個實例(每次只有一個線程在這段代碼中運行),不巧的是,性能上來講,鎖變成了每次都必須的當這個實例被響應的時候。
三、嘗試線程安全(雙重鎖定)不推薦使用
public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (padlock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
四、不徹底lazy,可是線程安全且不用用鎖 推薦使用
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); // 顯示的static 構造函數 //不必標記類型 - 在field初始化之前 static Singleton() { } private Singleton() { } public static Singleton Instance { get { return instance; } } }
歡迎關注個人公衆號(同步更新文章):DoNet技術分享平臺