【設計模式二】Singleton單例模式

前言

單例模式的實現方法很多,但是其中的門門道道很值得研究。

單例模式的意圖是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。這讓我們想到類的靜態函數只能由類來調用,這個方法就跟類的實例沒有關係了。這個方法的作用是獲取類的私有靜態類的指針。這個類的指針在類被聲明的時候就被初始化,並且是靜態的,跟實例無關,因此,每次調用靜態成員方法的時候,都會獲取同一個指針。

實現一:

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; //靜態類的指針,在聲明時被初始化
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章