C++單例模式的懶漢模式和餓漢模式詳解
懶漢模式
懶漢模式在第一次用到類(lèi)實(shí)例的時(shí)候才會(huì)去實(shí)例化,就是不到調(diào)用getInstance函數(shù)時(shí),這個(gè)類(lèi)的對(duì)象是一直不存在的。懶漢本身是線(xiàn)程不安全的。
#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;//定義一個(gè)唯一指向?qū)嵗闹羔?,并且是私有?
public:
static Singelton *GetSingelton();//定義一個(gè)公有函數(shù),可以獲取這個(gè)唯一實(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類(lèi)有以下特點(diǎn):
1.他有一個(gè)指向唯一實(shí)例的靜態(tài)指針,并且是私有的。
2.它有一個(gè)公有的函數(shù),可以獲取這個(gè)唯一的實(shí)例,并且在需要的時(shí)候創(chuàng)建該實(shí)例。
3.它的構(gòu)造函數(shù)是私有的,這樣就不能從別處創(chuàng)建該類(lèi)的實(shí)例。
餓漢模式
餓漢模式在單例類(lèi)定義的時(shí)候(即在main函數(shù)之前)就進(jìn)行實(shí)例化。因?yàn)閙ain函數(shù)執(zhí)行之前,全局作用域的類(lèi)成員靜態(tài)變量m_Instance已經(jīng)初始化,故沒(méi)有多線(xiàn)程的問(wèn)題。
#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;//定義一個(gè)唯一指向?qū)嵗闹羔槪⑶沂撬接械?
public:
static Singelton *GetSingelton();//定義一個(gè)公有函數(shù),可以獲取這個(gè)唯一實(shí)例
static void print();
static int m_count;
};
// 餓漢模式的關(guān)鍵:定義即實(shí)例化
Singelton *Singelton::single = new Singelton;
int Singelton::m_count = 0;
Singelton *Singelton::GetSingelton(){
// 不再需要進(jìn)行實(shí)例化
//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;
}
線(xiàn)程安全的懶漢模式
在多線(xiàn)程環(huán)境下,懶漢模式的上述實(shí)現(xiàn)方式是不安全的,原因在于在判斷instance是否為空時(shí),可能存在多個(gè)線(xiàn)程同時(shí)進(jìn)入if中,此時(shí)可能會(huì)實(shí)例化多個(gè)對(duì)象。于是出現(xiàn)了二重鎖的懶漢模式,實(shí)現(xiàn)代碼如下:
#include<iostream>
#include<mutex>
using namespace std;
/*單例模式:構(gòu)造函數(shù)私有化,對(duì)外提供一個(gè)接口*/
//線(xiàn)程安全的單例模式
class lhsingleClass {
public:
static lhsingleClass* getinstance()
{//雙重鎖模式
if (instance == nullptr)
{//先判斷是否為空,如果為空則進(jìn)入,不為空說(shuō)明已經(jīng)存在實(shí)例,直接返回
//進(jìn)入后加鎖
i_mutex.lock();
if (instance == nullptr)
{//再判斷一次,確保不會(huì)因?yàn)榧渔i期間多個(gè)線(xiàn)程同時(shí)進(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;//類(lèi)外初始化
int main()
{
lhsingleClass* lhsinglep5 = lhsingleClass::getinstance();
lhsingleClass* lhsinglep6 = lhsingleClass::getinstance();
cout << lhsinglep5 << endl;
cout << lhsinglep6 << endl;
system("pause");
return 0;
}
此代碼共進(jìn)行了兩次判斷:
- 先判斷是否為空,如果為空則進(jìn)入,不為空說(shuō)明已經(jīng)存在實(shí)例,直接返回。
- 再判斷一次,確保不會(huì)因?yàn)榧渔i期間多個(gè)線(xiàn)程同時(shí)進(jìn)入。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Qt實(shí)現(xiàn)驗(yàn)證碼相關(guān)功能的代碼示例
驗(yàn)證碼的原理基于人類(lèi)視覺(jué)和計(jì)算機(jī)視覺(jué)的差異性,通過(guò)給用戶(hù)顯示一些難以被機(jī)器識(shí)別的圖形或文字,讓用戶(hù)進(jìn)行人機(jī)交互,確認(rèn)自己的身份,這樣可以有效保護(hù)網(wǎng)站安全,所以本給大家介紹了Qt實(shí)現(xiàn)驗(yàn)證碼相關(guān)功能的代碼示例,感興趣的朋友可以參考下2024-01-01
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹(shù)的概念及滿(mǎn)二叉樹(shù)與完全二叉樹(shù)
在上一章中我們正式開(kāi)啟了對(duì)數(shù)據(jù)結(jié)構(gòu)中樹(shù)的講解,介紹了樹(shù)的基礎(chǔ)。本章我們將學(xué)習(xí)二叉樹(shù)的概念,介紹滿(mǎn)二叉樹(shù)和完全二叉樹(shù)的定義,并對(duì)二叉樹(shù)的基本性質(zhì)進(jìn)行一個(gè)簡(jiǎn)單的介紹。本章附帶課后練習(xí)2022-02-02
C語(yǔ)言進(jìn)階輸入輸出重定向與fopen函數(shù)使用示例詳解
這篇文章主要為大家介紹了C語(yǔ)言進(jìn)階輸入輸出重定向與fopen函數(shù)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
C++編程中的const關(guān)鍵字常見(jiàn)用法總結(jié)
這篇文章主要介紹了C++編程中的const關(guān)鍵字常見(jiàn)用法總結(jié),const關(guān)鍵字的使用是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-11-11
C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)版通訊錄的代碼分享
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的動(dòng)態(tài)版通訊錄,主要運(yùn)用了結(jié)構(gòu)體,一維數(shù)組,函數(shù),分支與循環(huán)語(yǔ)句等等知識(shí),需要的可以參考一下2023-01-01
C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05

