前言
單例模式的實現方法很多,但是其中的門門道道很值得研究。
單例模式的意圖是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。這讓我們想到類的靜態函數只能由類來調用,這個方法就跟類的實例沒有關係了。這個方法的作用是獲取類的私有靜態類的指針。這個類的指針在類被聲明的時候就被初始化,並且是靜態的,跟實例無關,因此,每次調用靜態成員方法的時候,都會獲取同一個指針。
實現一:
class CSingleton
{
public:
static CSingleton * GetInstance()
{
if(m_pInstance == NULL) //判斷是否第一次調用
m_pInstance = new CSingleton();
return m_pInstance;
}
private:
CSingleton() //構造函數是私有的
{
}
static CSingleton *m_pInstance; //靜態類的指針,在聲明時被初始化
};
這樣就可以了,保證只取得了一個實例。但是在多線程的環境下卻不行了,因爲很可能兩個線程同時運行到if (instance == NULL)這一句,導致可能會產生兩個實例。於是就要在代碼中加鎖。
實現二:
class CSingleton
{
public:
static CSingleton * GetInstance()
{
lock();
if(m_pInstance == NULL) //判斷是否第一次調用
{
m_pInstance = new CSingleton();
}
unlock();
return m_pInstance;
}
private:
CSingleton() //構造函數是私有的
{
}
static CSingleton *m_pInstance; //靜態類的指針,在聲明時被初始化
};
但這樣寫的話,會稍稍影響性能,因爲每次判斷是否爲空都需要被鎖定,如果有很多線程的話,就會造成大量線程的阻塞。於是有了改進:
class CSingleton
{
public:
static CSingleton * GetInstance()
{
if(m_pInstance == NULL) //先判斷一次
{
lock();
if(m_pInstance == NULL) //判斷是否第一次調用
{
m_pInstance = new CSingleton();
}
unlock();
}
return m_pInstance;
}
private:
CSingleton() {} //構造函數是私有的
static CSingleton *m_pInstance; //靜態類的指針,在聲明時被初始化
};