C++單例模式的懶漢模式和餓漢模式詳解
懶漢模式
懶漢模式在第一次用到類實例的時候才會去實例化,就是不到調(diào)用getInstance函數(shù)時,這個類的對象是一直不存在的。懶漢本身是線程不安全的。
#include <iostream> using namespace std; class Singelton{ private: Singelton(){ m_count ++; printf("Singelton begin\n"); Sleep(1000);// 加sleep為了放大效果 printf("Singelton end\n"); } static Singelton *single;//定義一個唯一指向?qū)嵗闹羔?,并且是私有? public: static Singelton *GetSingelton();//定義一個公有函數(shù),可以獲取這個唯一實例 static void print(); static int m_count; }; //將唯一指向?qū)嵗闹羔槼跏蓟癁閚ullptr Singelton *Singelton::single = nullptr; int Singelton::m_count = 0; Singelton *Singelton::GetSingelton(){ if(single == nullptr){//判斷是不是第一次使用 single = new Singelton; } return single; } void Singelton::print(){ cout<<m_count<<endl; } int main() { singleton* a1 = singleton::GetInstance(); cout << a1 << endl; a1->print(); singleton* a2 = singleton::GetInstance(); cout << a2 << endl; a2->print(); system("pause"); return 0; }
懶漢模式的singleton類有以下特點:
1.他有一個指向唯一實例的靜態(tài)指針,并且是私有的。
2.它有一個公有的函數(shù),可以獲取這個唯一的實例,并且在需要的時候創(chuàng)建該實例。
3.它的構(gòu)造函數(shù)是私有的,這樣就不能從別處創(chuàng)建該類的實例。
餓漢模式
餓漢模式在單例類定義的時候(即在main函數(shù)之前)就進(jìn)行實例化。因為main函數(shù)執(zhí)行之前,全局作用域的類成員靜態(tài)變量m_Instance已經(jīng)初始化,故沒有多線程的問題。
#include <iostream> #include <process.h> #include <windows.h> using namespace std; class Singelton{ private: Singelton(){ m_count ++; printf("Singelton begin\n"); Sleep(1000); // 加sleep為了放大效果 printf("Singelton end\n"); } static Singelton *single;//定義一個唯一指向?qū)嵗闹羔?,并且是私有? public: static Singelton *GetSingelton();//定義一個公有函數(shù),可以獲取這個唯一實例 static void print(); static int m_count; }; // 餓漢模式的關(guān)鍵:定義即實例化 Singelton *Singelton::single = new Singelton; int Singelton::m_count = 0; Singelton *Singelton::GetSingelton(){ // 不再需要進(jìn)行實例化 //if(single == nullptr){ // single = new Singelton; //} return single; } void Singelton::print(){ cout<<m_count<<endl; } int main() { cout << "we get the instance" << endl; singleton* a1 = singleton::getinstance(); singleton* a2 = singleton::getinstance(); singleton* a3 = singleton::getinstance(); cout << "we destroy the instance" << endl; system("pause"); return 0; }
線程安全的懶漢模式
在多線程環(huán)境下,懶漢模式的上述實現(xiàn)方式是不安全的,原因在于在判斷instance是否為空時,可能存在多個線程同時進(jìn)入if中,此時可能會實例化多個對象。于是出現(xiàn)了二重鎖的懶漢模式,實現(xiàn)代碼如下:
#include<iostream> #include<mutex> using namespace std; /*單例模式:構(gòu)造函數(shù)私有化,對外提供一個接口*/ //線程安全的單例模式 class lhsingleClass { public: static lhsingleClass* getinstance() {//雙重鎖模式 if (instance == nullptr) {//先判斷是否為空,如果為空則進(jìn)入,不為空說明已經(jīng)存在實例,直接返回 //進(jìn)入后加鎖 i_mutex.lock(); if (instance == nullptr) {//再判斷一次,確保不會因為加鎖期間多個線程同時進(jìn)入 instance = new lhsingleClass(); } i_mutex.unlock();//解鎖 } return instance; } private: static lhsingleClass* instance; static mutex i_mutex;//鎖 lhsingleClass(){} }; lhsingleClass* lhsingleClass::instance=nullptr; mutex lhsingleClass::i_mutex;//類外初始化 int main() { lhsingleClass* lhsinglep5 = lhsingleClass::getinstance(); lhsingleClass* lhsinglep6 = lhsingleClass::getinstance(); cout << lhsinglep5 << endl; cout << lhsinglep6 << endl; system("pause"); return 0; }
此代碼共進(jìn)行了兩次判斷:
- 先判斷是否為空,如果為空則進(jìn)入,不為空說明已經(jīng)存在實例,直接返回。
- 再判斷一次,確保不會因為加鎖期間多個線程同時進(jìn)入。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹的概念及滿二叉樹與完全二叉樹
在上一章中我們正式開啟了對數(shù)據(jù)結(jié)構(gòu)中樹的講解,介紹了樹的基礎(chǔ)。本章我們將學(xué)習(xí)二叉樹的概念,介紹滿二叉樹和完全二叉樹的定義,并對二叉樹的基本性質(zhì)進(jìn)行一個簡單的介紹。本章附帶課后練習(xí)2022-02-02C語言進(jìn)階輸入輸出重定向與fopen函數(shù)使用示例詳解
這篇文章主要為大家介紹了C語言進(jìn)階輸入輸出重定向與fopen函數(shù)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02C++編程中的const關(guān)鍵字常見用法總結(jié)
這篇文章主要介紹了C++編程中的const關(guān)鍵字常見用法總結(jié),const關(guān)鍵字的使用是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05