三、餓漢式單例
參考文章:
設計模式(一)–深入單例模式(涉及執行緒安全問題)。**全,解釋清楚。
本篇部落格編譯時,需要使用c++11標準。
(1)定義:
要求乙個類只能生成乙個物件,所有物件對它的依賴相同。
(2)優點:
(3)缺點:
(4)使用場景:
(5)注意事項:
懶漢式單例就是需要使用這個單例物件的時候才去建立這個單例物件。
#include
#include
#include
#include
#ifdef win32
#include
#define sleep(x) sleep(x)
#else
#include
#define sleep(x) usleep(x*1000)
#endif
using namespace std;
//懶漢式單例
class singleton
return singleton;}}
;// 必須在類外初始化
singleton* singleton:
:singleton = nullptr;
// 定義乙個互斥鎖
mutex m;
void
print_address()
intmain()
執行結果:
0x7ff280000b20
0x7ff298000b20
0x7ff290000b20
0x7ff288000b20
0x7ff278000b20
0x7ff260000b20
0x7ff268000b20
0x7ff264000b20
0x7ff258000b20
0x7ff270000b20
可以看出,結果裡面有好幾個不同位址的例項!所以,這種單例模式不是執行緒安全的。原因是,當幾個執行緒同時執行到語句if (singleton::singleton == nullptr)
時,singleton都還沒有被建立,所以就重複建立了幾個例項。
為了編寫執行緒安全的單例模式,可以鎖住getinstance函式,保證同時只有乙個執行緒訪問getinstance函式(為了節省篇幅,相同的部分不在**中再次給出)。
using namespace std;
//執行緒安全的懶漢式單例
mutex m1;
class singleton
m1.unlock()
;//解鎖
return singleton;}}
;
執行輸出:
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
0x7fcb80000b20
可以發現,所有執行緒獲取到的例項的位址都相同。整個程式中只有乙個singleton例項。原因是進入getinstance
函式之後,立馬鎖住建立例項的語句,保證只有乙個執行緒在訪問建立例項的**。
僅僅對建立例項的語句進行加鎖,是否是執行緒安全的呢?
//執行緒安全的懶漢式單例
mutex m1;
class singleton
return singleton;}}
;
執行輸出:
0x7ff7f0000b20
0x7ff7e8000b20
0x7ff7f0000f50
0x7ff7ec000b20
0x7ff7e0000b20
0x7ff7ec000b40
0x7ff7f0000f70
0x7ff7e0000b40
0x7ff7f0000f90
0x7ff7ec000b60
這種方式不是執行緒安全的。因為當執行緒同時執行到語句if (singleton::singleton == nullptr)
時,singleton都還沒有被建立,故會條件為真,多個執行緒都會建立例項,儘管不是同時建立。
//執行緒安全的懶漢式單例
mutex m1;
class singleton
m1.unlock()
;//解鎖
}return singleton;}}
;
執行輸出:
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
0x7f0bc4000b20
可以看出,這種方式是執行緒安全的。並且沒有第2種**簡潔。
先例項化該單例類,而不是像之前一樣初始化為空指標。
using namespace std;
//執行緒安全的餓漢式單例
class singleton catch (exception& e)
singleton
(const singleton& s)
=default
; singleton& operator=
(const singleton& s)
=default
;public:
static singleton*
getinstance()
};// 必須在類外初始化
singleton* singleton:
:singleton = new singleton()
;// 定義乙個互斥鎖
mutex m;
執行輸出:
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
0x56362e1fae70
可以看出singleton的例項確實只有乙個。餓漢式單利會在程式開始之前就被建立,所以是執行緒安全的。由於建立的單例是在全域性變數區,所以需要處理建構函式中可能出現的異常:
singleton
() trycatch (exception& e)
這裡涉及到的知識是:很少有人知道的c++中的try塊函式。
至於參考部落格中提到的序列化與反序列化問題,不在本部落格中做討論。
C 單例模式詳解
下面是對應的c 單例模式物件推導過程,如果大家有興趣可以慢慢看下去,想直接看結果的請看最後乙個版本的 pragma include class csingletion return m pstaticsingletion todo 實現功能 void work private csingletion...
單例模式詳解
單例模式的意思就是只有乙個例項。單例模式確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。這個類稱為單例類。1.單例模式的要點 顯然單例模式的要點有三個 一是某個類只能有乙個例項 二是它必須自行建立這個例項 三是它必須自行向整個系統提供這個例項。2.單例模式的優點 1.例項控制 si...
單例模式詳解
單例模式是設計模式中比較常用的,今天我要詳細的了解一下,並且進行一些比較 public class singleton public static singleton getinstance catch interruptedexception e 單例模式的精髓就在這,類的內部可以new inst...