一、基礎的單例模式實現
- 構造函數聲明爲 private 或 protect ,防止被外部函數實例化;
- 內部保存一個 private static 的類指針保存唯一的實例;
- 實例的動作由一個 public 的類方法如 getInstance( ) 完成,該方法也返回單例類唯一的實例。
- 具體實現
class singleton
{
protected:
singleton(){}
private:
static singleton* p;
public:
static singleton* getInstance();
};
singleton* singleton::p = NULL;
singleton* singleton::getInstance()
{
if (p == NULL)
p = new singleton();
return p;
}
看起來一切都很優雅,但是!該方法是線程不安全的,如果有兩個線程同時首次調用getInstance()方法且同時檢測到p是NULL值,則兩個線程會同時構造一個實例給p,顯然這是錯誤的。
二、懶漢模式與餓漢模式
1. 單例的兩類實現方法
- 懶漢:在第一次用到類實例的時候纔會去實例化,故上邊的經典方法被歸爲懶漢實現;
- 餓漢:在單例類定義的時候就進行實例化。
2. 特點與選擇:
- 以空間換時間:由於要進行線程同步,所以在訪問量比較大,或者可能訪問的線程比較多時,採用餓漢實現。
- 以時間換空間:在訪問量較小時,採用懶漢實現。
3. 餓漢模式實現:
class singleton
{
protected:
singleton(){}
private:
static singleton* p;
public:
static singleton* getInstance();
};
singleton* singleton::p = new singleton; //單例類定義的時候就進行實例化
singleton* singleton::getInstance()
{
return p;
}
4. 線程安全的懶漢模式實現
- 加鎖
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* getInstance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::getInstance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
- 內部靜態變量
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* getInstance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::getInstance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
此方法在 getInstance 函數裏定義一個靜態的實例,也可以保證擁有唯一實例,在返回時只需要返回其指針。