詳解C 實現執行緒安全的單例模式

2022-09-29 21:45:28 字數 4104 閱讀 3702

在某些應用環境下面,乙個類只允許有乙個例項,這就是著名的單例模式。單例模式分為懶漢模式,跟餓漢模式兩種。

首先給出餓漢模式的實現

正解:template

class singleton

;private:

singleton(const singleton&){};//禁止拷貝

singleton& operator=(const singleton&){};//禁止賦值

static t* m_instance;

public:

static t* getinstance();};

template

t* singleton::getinstance()szzhzpdxpc

template

在例項化m_instance 變數時,直接呼叫類的建構函式。顧名思義,在還未使用變數時,已經對m_instance進行賦值,就像很飢餓的感覺。這種模式,在多執行緒環境下肯定是執行緒安全的,因為不存在多執行緒例項化的問題。

下面來看懶漢模式

template

class singleton

;private:

singleton(const singleton&){};

singleton& operator=(const singleton&){};

static t* m_instance;

publiszzhzpdxpcc:

static t* getinstance();};

template

t* singleton::getinstance()

return m_instance;}

template

t* singleton::m_instance = null;

懶漢模式下,在定義m_instance變數時先等於null,在呼叫getinstance()方法時,在判斷是否要賦值。這種模式,並非是執行緒安全的,因為多個執行緒同時呼叫getinstance()方法,就可能導致有產生多個例項。要實現執行緒安全,就必須加鎖。

下面給出改進之後的**

template

class singleton

;private:

singleton(const singleton&){};

singleton& operator=(const singleton&){};

static t* m_instance;

static pthread_mutex_t mutex;

public:

static t* getinstance();}; 

template

t* singleton::getinstance()

pthread_mutex_unlock(&mutex);

return m_instance;} 

template

pthread_mutex_t singleton::mutex = pthread_mutex_initializer;

template

t* singleton::m_instance = null;

這一切看起來都很完美,但是程式猿是一種天生就不知道滿足的動物。他們發現getinstance()方法,每次進來都要加鎖,會影響效率。然而這並不是必須的,於是又對getinstance()方法進行改進

template

t* singleton::getinstance()

pthread_mutex_unlock(&mutex);

} return m_instance;

}這也就是所謂的「雙檢鎖」機制。但是有人質疑這種實現還是有問題,在執行 m_instance = new t()時,可能 類t還沒有初始化完成,m_instance 就已經有值了。這樣會導致另外乙個呼叫getinstance()方法的執行緒,獲取到還未初始化完成的m_instance 指標,如果去使用它,會有意料不到的後果。其實,解決方法也很簡單,用乙個區域性變數過渡下即可:

正解:template

t* singleton::getinstance()

pthread_mutex_unlock(&mutex);

} return m_instance;

}到這裡在懶漢模式下,也就可以保證執行緒安全了。

然而,在linux下面還有另一種實現。linux提供了乙個叫pthread_once()的函式,它保證在乙個程序中,某個函式只被執行一次。下面是使用pthread_once實現的執行緒安全的懶漢單例模式

template

class singleton

;private:

singleton(const singleton&){};

singleton& operator=(const singleton&){};

static t* m_instance;

static pthread_once_t m_once;

public:

static void init();

static t* getinstance();};

template

void singleton::init()

template

t* singleton::getinstance()

template

pthread_once_t singleton::m_once = pthread_once_init;

template

t* singleton::m_instance = null;

上面的單例類使用了模板,對每一種型別的變數都能例項化出唯一的乙個例項。

例如要例項化乙個int型別

int *p = singleton::getinstance()

例如要例項化乙個string型別

string *p = singleton::getinstance()

在上面的實現中,在例項化物件時,呼叫getinstance()函式時都沒有傳遞引數,這是猶豫不同的物件其初始化時引數個數都不一樣。如果要支援不同型別的物件帶引數初始化,則需要過載getinstance函式。然而在c++11中,已經支援了可變引數函式。這裡給出乙個簡單的例子

#ifndef _singleton_h_

#define _singleton_h_

template

class singleton

;private:

singleton(const singleton&){};

singleton& operator=(const singleton&){};

static t* m_instance;

public:

template

static t* getinstance(args&&... args)

static void destroyinstance()

};

template

t* singleton::m_instaszzhzpdxpcnce = null;

#endif

測試函式

#include

#include

#include "singleton.h"

using namespace std;

struct a

int _a;

int _b;};

int main()

{ int *p1 = singleton::getinstance(5);

int *p2 = singleton::getinstance(10);

cout << *p1 << " " << *p2 <::getinstance>

string *p4 = singleton::getinstance("bb");

cout << *p3 << " " << *p4 <::getinstance>

a *p6 = singleton::getinstance(4,5);

cout << p5->_a << " " << p6->_a<

執行結果如下

本文標題: 詳解c++實現執行緒安全的單例模式

本文位址: /ruanjian/c/254401.html

C 實現執行緒安全的單例模式

廢話不多說,常用的 積澱下來。一 懶漢模式 即第一次呼叫該類例項的時候才產生乙個新的該類例項,並在以後僅返回此例項。需要用鎖,來保證其執行緒安全性 原因 多個執行緒可能進入判斷是否已經存在例項的if語句,從而non thread safety.使用double check來保證thread safe...

c 多執行緒單例模式 執行緒安全C 單例模式

我對此處記錄的單例模式有一些疑問 http us library ff650316.aspx 以下 摘自該文章 using system public sealed class singleton private static volatile singleton instance private ...

從C 單例模式到執行緒安全詳解

先看乙個最簡單的教科書式單例模式 class csingleton return ps 程式設計客棧 private csingleton csingleton operator const csingleton s static csingleton ps csingleton csingleto...