C++單列模式_學(xué)到牛牛

單例模式是一種最為常見的軟件設(shè)計模式金句。單例模式要求:單例對象所在的類必須保證只能創(chuàng)建一個對象蛾娶。單例模式在我們?nèi)粘I詈蛙浖_發(fā)中的應(yīng)用比比皆是碾褂,比如:windows系統(tǒng)只有一個任務(wù)管理器榆俺,一個市只有一個市長骑歹。

如何保證一個類最多只能創(chuàng)建一個對象呢预烙?這個問題不能交由使用者去做處理,比如用全局變量道媚。而應(yīng)該由這個類的創(chuàng)建者在實現(xiàn)該類的時候考慮問題的解決扁掸。

單例模式巧妙的使用C++成員權(quán)限,將構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)隱藏起來(private)最域,從而有效限定使用中對對象的自由創(chuàng)建谴分。然后開放一個(static)接口,通過靜態(tài)方法創(chuàng)建對象镀脂,并在靜態(tài)方法中限定對象的唯一創(chuàng)建牺蹄。

單例模式的創(chuàng)建方式一般有兩種:懶漢式和餓漢式。

1.懶漢模式

懶漢:顧名思義薄翅,不到萬不得已該類不會去實例化對象沙兰。將對象的示例推遲到需要該對象的時候。

// 單例模式之懶漢模式

class Singleton{

public:

static Singleton* createSingleton(){ // static方法

if( m_handler == nullptr ){

m_handler = new Singleton();

}

return m_handler;

}

private:

Singleton(); //? 私有化構(gòu)造函數(shù)

~Singleton(); //? 私有化析構(gòu)函數(shù)

Singleton( const Singleton & ); //? 私有化拷貝構(gòu)造函數(shù)翘魄,防止通過拷貝構(gòu)造復(fù)制對象

static Singleton* m_handler;

};

Singleton* Singleton::m_handler = nullptr;

int main()

{

Singleton *ptr1 = Singleton::createSingleton();

Singleton *ptr2 = ptr1-> createSingleton();? // ptr1 和 ptr2 指向同一個對象

return 0;

}

2.餓漢模式

餓漢:單例類在創(chuàng)建類的時候就創(chuàng)建了對象鼎天。

// 單例模式之餓漢模式

class Singleton{

public:

static Singleton* getSingleton(){

return m_handler;

}

private:

Singleton(); //? 私有化構(gòu)造函數(shù)

~Singleton(); //? 私有化析構(gòu)函數(shù)

Singleton( const Singleton & ); //? 私有化拷貝構(gòu)造函數(shù),防止通過拷貝構(gòu)造復(fù)制對象

static Singleton* m_handler;

};

Singleton* Singleton::m_handler = new Singleton; // 類創(chuàng)建時暑竟,創(chuàng)建對象

int main()

{

Singleton *ptr1 = Singleton::createSingleton();

Singleton *ptr2 = ptr1-> createSingleton();? // ptr1 和 ptr2 指向同一個對象

return 0;

}

3.單例模式中的線程安全

前面我們考慮了單例模式的懶漢式和餓漢式斋射,但是我們只考慮了普通單線程情況。如果考慮到多線程情況,那么上面的懶漢模式則不是線程安全的罗岖。而餓漢模式因為在編譯階段已經(jīng)創(chuàng)建了對象涧至,所有它是線程安全的。

如何解決懶漢模式的線程不安全呢桑包?通常情況我們可以通過互斥鎖解決臨界資源的訪問問題南蓬。

// 單例模式之懶漢模式+線程安全

class Singleton{

public:

static Singleton* createSingleton(){ // static方法

if( m_handler == nullptr ){? // 解決訪問效率問題

pthread_mutex_lock( &m_lock );

if( m_handler == nullptr ){

m_handler = new Singleton();

}

pthread_mutex_unlock( &m_lock );

return m_handler;

}

}

private:

Singleton(); //? 私有化構(gòu)造函數(shù)

~Singleton(); //? 私有化析構(gòu)函數(shù)

Singleton( const Singleton & ); //? 私有化拷貝構(gòu)造函數(shù),防止通過拷貝構(gòu)造復(fù)制對象

static Singleton* m_handler;

static pthread_mutex_t? m_lock;

};

Singleton* Singleton::m_handler = nullptr;

pthread_mutex_t? Singleton::m_lock = PTHREAD_MUTEX_INITIALIZER;

int main()

{

Singleton *ptr1 = Singleton::createSingleton();

Singleton *ptr2 = ptr1-> createSingleton();? // ptr1 和 ptr2 指向同一個對象

return 0;

}

上面例程通過互斥鎖捡多,看似解決了多線程中的臨界資源互斥問題蓖康。但是實際上并非如此铐炫。具體問題如下:

上面代碼中:m_handler = new Singleton();? 我們期望的執(zhí)行順序是:

(1)分配一段內(nèi)存? (2)構(gòu)造對象垒手,放入內(nèi)存? (3)m_handler存內(nèi)存地址

但是實際執(zhí)行可能是:

(1)分配一段內(nèi)存? (2) m_handler存內(nèi)存地址? (3)構(gòu)造對象,放入內(nèi)存

那么后面的情況可能導(dǎo)致倒信,對象還沒創(chuàng)建科贬,但是已經(jīng)被另外一個線程拿去使用了,這種情況可能導(dǎo)致嚴(yán)重錯誤鳖悠。那么如何解決呢榜掌?大家可以思考一下。

文章來源:學(xué)到牛牛 www.xuedaon.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乘综,一起剝皮案震驚了整個濱河市憎账,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卡辰,老刑警劉巖胞皱,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異九妈,居然都是意外死亡反砌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門萌朱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宴树,“玉大人,你說我怎么就攤上這事晶疼【票幔” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵翠霍,是天一觀的道長同衣。 經(jīng)常有香客問我,道長壶运,這世上最難降的妖魔是什么耐齐? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上埠况,老公的妹妹穿的比我還像新娘耸携。我一直安慰自己,他們只是感情好辕翰,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布夺衍。 她就那樣靜靜地躺著,像睡著了一般喜命。 火紅的嫁衣襯著肌膚如雪沟沙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天壁榕,我揣著相機與錄音矛紫,去河邊找鬼。 笑死牌里,一個胖子當(dāng)著我的面吹牛颊咬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牡辽,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼喳篇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了态辛?” 一聲冷哼從身側(cè)響起麸澜,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奏黑,沒想到半個月后炊邦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡攀涵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年铣耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片以故。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜗细,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怒详,到底是詐尸還是另有隱情炉媒,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布昆烁,位于F島的核電站吊骤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏静尼。R本人自食惡果不足惜白粉,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一传泊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸭巴,春花似錦眷细、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恬口,卻和暖如春校读,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祖能。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工歉秫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芯杀。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓端考,卻偏偏與公主長得像雅潭,于是被迫代替她去往敵國和親揭厚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容