单例模式双重校验锁_滴滴面试官:如何实现一个线程安全的单例模式
單例模式作為最常見的設計模式,有很多實現方式,今天介紹一下單例模式相關的內容。
什么是單例模式
從字面上理解,單例模式需要確保一個類只有一個對象。比如線程池、緩存、日志對象、打印機驅動對象、顯卡驅動對象等,這些類的對象往往只需要一個實例就可以。如果一個類的對象需要被頻繁創建,那么也會需要頻繁GC,單例模式就可以解決這樣的問題。
單例模式的實現方式
單例模式的實現方式非常多,但總體上可以分為兩類:餓漢式和懶漢式。餓漢式是在類加載過程中就創建對象的方式,而懶漢式是需要使用時才會去創建對象的方式,這兩種方式各有特點。餓漢式存在的問題是如果要創建的對象占用的空間非常大,且使用頻率非常低,那么這種方式是非常不劃算的。而懶漢式有可能會遇到并發問題,這就要求我們需要考慮對創建對象的過程進行加鎖。不管是餓漢式還是懶漢式,創建的對象一般都得使用static關鍵字進行修飾。
餓漢式單例
public class Singleton {private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;} }上面的餓漢式單例在類加載時創建了一個對象,然后創建了一個private修飾的構造方法防止通過構造方法創建對象。
懶漢式單例(非線程安全版)
public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;} }上面這種單例方式的創建我們可以很容易看出當需要使用這個對象時才會去創建,滿足懶漢式的要求。但是這種創建單例的方式是有缺陷的,當多個線程同時獲取對象,在判斷對象是否為空的地方,如果兩個線程同時到達,那么就會同時進入這個條件中,創建多個對象。下面提出一些線程安全的懶漢式單例。
懶漢式單例(synchronized修飾的線程安全版)
public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;} }基于上面的非線程安全版本,我們在getInstance()方法上加上了synchronized鎖,就變成了線程安全的版本。但是這種直接在方法上加鎖的方式其實對并發的效率影響是很大的,盡管在JDK6中對synchronized做了很大優化,但是仍然不能滿足我們對高并發的要求,下面介紹一下更加高效的雙重校驗鎖版。
懶漢式單例(雙重校驗鎖版)
public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized(Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;} }我們又基于前面的非線程安全的版本實現了這個雙重校驗鎖版的懶漢式單例,如果多個線程同時在外層判斷對象為空時,開始搶占鎖資源,搶到的線程創建對象,其他線程就不再需要創建線程了。這種方式的優點在于只有第一次搶奪資源的時候需要進行同步,后續的并發都會判斷對象不為空,直接返回對象。
懶漢式單例(靜態內部類版)
public class Singleton {//靜態內部類private static class SingletonHandler {private static Singleton instance = new Singleton();}private Singleton() {}public static Singleton getInstance() {return SingletonHandler.instance;} }該方式依然是懶漢式單例,只不過利用靜態內部類實現,同樣也是線程安全的。
餓漢式單例(枚舉版)
public class EnumSingleton {private EnumSingleton() {}public static EnumSingleton getInstance(){return Singleton.singletonFactory.getInstance();}private enum Singleton {singletonFactory;private EnumSingleton instance;private Singleton() { //枚舉類的構造方法在類加載時被實例化instance = new EnumSingleton();}public EnumSingleton getInstance() {return instance;}} }上面是利用枚舉創建單例對象的方法,利用枚舉類加載時會實例化構造方法的特點進行單例模式的實現,是一種比較推薦使用的方法。
總結
以上是生活随笔為你收集整理的单例模式双重校验锁_滴滴面试官:如何实现一个线程安全的单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python整数类型提供了4种进制表示_
- 下一篇: 谷歌扇区图层制作工具_很实用!轻松实现M