C++單例模式的懶漢模式和餓漢模式詳解
懶漢模式
懶漢模式在第一次用到類實例的時候才會去實例化,就是不到調用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;//定義一個唯一指向實例的指針,并且是私有的
public:
static Singelton *GetSingelton();//定義一個公有函數(shù),可以獲取這個唯一實例
static void print();
static int m_count;
};
//將唯一指向實例的指針初始化為nullptr
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.它的構造函數(shù)是私有的,這樣就不能從別處創(chuàng)建該類的實例。
餓漢模式
餓漢模式在單例類定義的時候(即在main函數(shù)之前)就進行實例化。因為main函數(shù)執(zhí)行之前,全局作用域的類成員靜態(tài)變量m_Instance已經初始化,故沒有多線程的問題。
#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;//定義一個唯一指向實例的指針,并且是私有的
public:
static Singelton *GetSingelton();//定義一個公有函數(shù),可以獲取這個唯一實例
static void print();
static int m_count;
};
// 餓漢模式的關鍵:定義即實例化
Singelton *Singelton::single = new Singelton;
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()
{
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是否為空時,可能存在多個線程同時進入if中,此時可能會實例化多個對象。于是出現(xiàn)了二重鎖的懶漢模式,實現(xiàn)代碼如下:
#include<iostream>
#include<mutex>
using namespace std;
/*單例模式:構造函數(shù)私有化,對外提供一個接口*/
//線程安全的單例模式
class lhsingleClass {
public:
static lhsingleClass* getinstance()
{//雙重鎖模式
if (instance == nullptr)
{//先判斷是否為空,如果為空則進入,不為空說明已經存在實例,直接返回
//進入后加鎖
i_mutex.lock();
if (instance == nullptr)
{//再判斷一次,確保不會因為加鎖期間多個線程同時進入
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;
}
此代碼共進行了兩次判斷:
- 先判斷是否為空,如果為空則進入,不為空說明已經存在實例,直接返回。
- 再判斷一次,確保不會因為加鎖期間多個線程同時進入。
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
C語言數(shù)據(jù)結構系列篇二叉樹的概念及滿二叉樹與完全二叉樹
在上一章中我們正式開啟了對數(shù)據(jù)結構中樹的講解,介紹了樹的基礎。本章我們將學習二叉樹的概念,介紹滿二叉樹和完全二叉樹的定義,并對二叉樹的基本性質進行一個簡單的介紹。本章附帶課后練習2022-02-02
C語言進階輸入輸出重定向與fopen函數(shù)使用示例詳解
這篇文章主要為大家介紹了C語言進階輸入輸出重定向與fopen函數(shù)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-02-02
C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)的相關資料,需要的朋友可以參考下2017-05-05

