一些單例模式的寫法與執行緒安全的分析

2021-09-02 00:18:10 字數 2314 閱讀 8068

要實現單例模式,最主要的就是 私有化 建構函式,然後提供乙個對外呼叫的方法,去建立乙個唯一的物件。

/**

這是一種懶漢方法建立的單例模式,是執行緒不安全的

**/@nothreadsafe //自定義的註解,標記執行緒不安全的類

public class nosafeexample1

public static nosafeexample1 getinstance()

return instance;}}

缺點:在多執行緒環境下,是執行緒不安全的,假如有兩個執行緒同時進行訪問該類,拿到了 instance = null 的值,就會建立出不止乙個物件。

@threadsafe

public class safeexample1

//採用synchronized 來確保執行緒的安全

public static synchronized safeexample1 getinstance()

return instance;}}

缺點:採用synchronized 鎖住這個方法,使執行緒達到安全,當併發量達到一定程度的時候,會造成效能下降。

public class nosafeexample2 

public static nosafeexample2 getinstance()}}

return instance;}}

缺點:這種寫法即使採用 synchronized 也是執行緒不安全的,不安全在  instance = new nasafeexample2()這個語句

instance = new nosafeexample2();

在程式中分三步進行執行

1. memory = allocate() 分配物件的記憶體空間

2. ctorinstance() 初始化物件

3. instance = memory 設定instance 指向記憶體的分配空間

由於cpu與jvm的優化,會將沒有關聯的指令進行重排

可能造成的順序為 1,3,2

假設現在有兩個執行緒

執行緒a 執行到 instance = new nosafeexample2(); 此時的指令順序是經過指令重排的

執行緒a執行了第3部,還未執行第2步

執行緒b執行到 instance == null,由於執行緒a行了第3步,所以 instance != null,直接返回

instance,但執行緒a還未執行第2步,所以是有問題的。

public static nosafeexample2 getinstance()}}

return instance;

}

解決方案: 加 volatile 關鍵字 作用 防止 指令重排 與 可見行

private volatile static nosafeexample2 instance = null;      // 就是執行緒安全的了。

/**

餓漢式單例模式,在類載入的時候就建立物件,是執行緒安全的

**/public class safeexample2

public static safeexample2 getinstance()

}

缺點:由於在類載入的時候就建立物件,如果物件過大,就會導致響應時間變長。

採用列舉類進行單例的實現

簡單的寫法:

public enum safeexample3

}複雜的寫法,可能不是太嚴謹

public class safeexample3

public static safeexample3 getinstance()

private enum singleton

public safeexample3 getsingleton() }}

如果是其他的方式實現單例模式,可能會存在 1. 反射 2.序列話問題。

這裡主要參考了部落格:

這邊簡單的說一下:

1.反射可以通過借助accessibleobject.setaccessible方法,通過反射機制呼叫私有構造器,並且呼叫,就可以建立多個物件;

標有黃色那行是  反射的原始碼,反射在通過newinstance建立物件時,會檢查該類是否enum修飾,如果是則丟擲異常,反射失敗。

2.序列化,readobject 會建立新的物件

執行緒安全的單例模式寫法

關於單例的理論部分已經不再贅述,網上多得是,下面以 為例 class cnoncopyable cnoncopyable private 將拷貝構造和賦值操作符宣告為私有型別 cnoncopyable const cnoncopyable const cnoncopyable operator co...

設計模式 單例模式的寫法(基礎寫法和執行緒安全寫法)

單例模式的寫法非常多。先給出一種最基礎的寫法 a種寫法 package singleton public class singletoninstance public static singletoninstance getinstance return msingletoninstance a寫法...

設計模式 單例模式的寫法(基礎寫法和執行緒安全寫法)

單例模式的寫法很多,先給出一種最基礎的寫法 a種寫法 package singleton public class singletoninstance public static singletoninstance getinstance return msingletoninstance a寫法是...