基於C++的單例模式

單例模式是一種設計模式.
單例模式表示在定義的某一個類中,只能有唯一的一個對象(即只能有一個實例).
優點:提高了封裝性,外部不能輕易的改變實例.

餓漢模式

含義:程序啓動後就會立即加載到內存.
缺點:啓動比較慢.
代碼如下:

#include <iostream>
using namespace std;

template<class T>
class Singleton
{
public:
    static T* GetSingleton()
    {
        return &value;
    }
private:
    static T value;
};
template<class T>
T Singleton<T>::value = T();

int main()
{
    Singleton<int>::GetSingleton();
    return 0;
}

懶漢模式

含義:啓動的時候不加載,只有當使用的時候纔會加載到內存.

#include <iostream>
using namespace std;

//懶漢模式
template<class T>   //類模板
class singleton
{
public:
    static T* GetSingleton()
    {
        if(value == NULL)
        {
            value = new T();
        }
        return value;
    }
private:
    static T* value;
};
template<class T>
T* singleton<T>::value = NULL;

int main()
{
    singleton<int>::GetSingleton();
    return 0;
}

上面這個代碼存在一個很重要的問題:

1.如果在多線程的環境下,在函數GetSingleton()中如果進行判斷時如果同時多個線程頻繁的進行判斷,那麼就會存在線程安全問題,如果多個線程都判斷爲空那麼就會new出來很多對象,那麼明顯就是不安全的.
解決:加鎖,在判斷前進行加鎖,在出了if判斷再進行解鎖.
問題:如果有多個進程頻繁的獲取鎖,然後再進行判斷,然後再釋放.那麼效率就會下降,加鎖和解鎖也是一種消耗.
解決:在加鎖前再進行一次判斷,如果爲空才進行進行加鎖.這樣就會大大減少了加解鎖的消耗.

具體的代碼如下:
template<class T>
class singleton
{
public:
    static T* GetSingleton()
    {
        if(value == NULL)    //這樣就只有爲空纔會進來進行加鎖解鎖(這樣就不會頻繁獲取鎖)
        {
            lock(); //這是一句僞代碼(加鎖)
            //如果在這兒加鎖,所有的線程到這兒都會先加鎖(這也是一種消耗),再判斷,這樣就會造成效率低.所以在這兒之前再進行一次判斷
            //但是在這兒加鎖也會滿足線程安全
            if(value == NULL)
            {
                value = new T();
            }
            unlock();  //僞代碼(解鎖)
        }
        return value;
    }
private:
    static volatile  T* value;  //加上volatile爲了防止編譯器過度優化
};
template<class T>
volatile T* singleton<T>::value = NULL;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章