線程安全單例(用Qt原子指針和模板實現)和單線程單例

   最近比較比較悠閒,複習了下設計模式中的單例模式,對於單例模式,網上有不少實例,可是看來看去,不少感受總是差點什麼,固然也有比較多的寫的很好,因此決定本身動手練習下,順便記錄下,就當記筆記了。html

  在實際的開發中,幾乎每一個項目都使用到單例模式,由於不少時候,一個類只能建立一個對象,即存在惟一實例,單例就是最恰當的解決辦法了。下面就分爲在單線程中和多線程的來記錄吧!設計模式

  在單線程中,網上有不少懶漢模式,餓漢模式什麼的,這些能夠本身去百度,就說下我本身比較經常使用的一種,直接上代碼比較直觀:安全

class CSingletonTwo
{
private:
    CSingletonTwo(){}//構造函數私有
public:
    static CSingletonTwo& getInstance(void);
    void init(void)
    {
        qDebug()<<" Test CSingletonTwo..........";
    }
};
CSingletonTwo& CSingletonTwo::getInstance()
{
    static CSingletonTwo instance;
    return instance;
}

這種方法(前提單線程中使用這個單例)我感受是比較簡單明瞭的一種,網上還有一些用下面方法實現,但感受仍是不如上面的簡單明瞭(固然,各有的想法,蘿蔔青菜,各有所愛。),如:多線程

class singleton
{
protected:
    singleton(){}
private:
    static singleton* p;

public:
    static singleton* instance();

};

singleton* singleton::p = NULL;

singleton* singleton::instance()
{

    if (p == NULL)
        p = new singleton();
    return p;
} 

 

  多線程安全模式,用到了Qt的原子指針和C++模板,具體以下:函數

#include <QCoreApplication>
#include <QAtomicPointer>
#include <QReadWriteLock>
#include <QMutex>
#include <qDebug>

template<class T>
class CSingleton
{
private:
    CSingleton();//防止構造函數
    CSingleton(const CSingleton<T> &);//防止拷貝構造函數
    CSingleton<T>& operator=(const CSingleton<T>&);//防止賦值拷貝構造函數

    QReadWriteLock m_internalMutex;//讀寫鎖
    static QMutex m_mutex;//互斥鎖
    static QAtomicPointer<T> m_instance;//實例

public:
    static T& getInstance(void);//獲取惟一實例
};

template<class T>
QMutex CSingleton<T>::m_mutex(QMutex::Recursive);//一個線程能夠屢次鎖同一個互斥量

template<class T>
QAtomicPointer<T>CSingleton<T>::m_instance;//原子指針,默認初始化是0

template<typename T>
T& CSingleton<T>::getInstance(void)
{
#ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
    if(!QAtomicPointer<T>::isTestAndSetNative())//運行時檢測
#endif
    {
        QMutexLocker locker(&m_mutex);//互斥鎖
        if(m_instance.testAndSetOrdered(0, 0))//第一次檢測
        {
            m_instance.testAndSetOrdered(0, new T);//第二次檢測
        }
        return *m_instance.load();
    }
}
class CTest
{
public:
    CTest(){}
    void init(void)
    {
        qDebug()<<" Test singteon!!!!!!!!!!";
    }
};
typedef CSingleton<CTest> test;//這裏使用CTest來實例化這個模板,還能夠本身定義其餘類了來實例化,省去在每一個使用單例的類中都實現一個單例的麻煩了

上面的多線程模式及其原子操做,參考了:https://www.cnblogs.com/codingmylife/archive/2010/07/14/1777409.html,可是在這基礎上加入了模板來實現,使用多種類型。我看網上也有使用繼承來達到單例適用多個類型,那樣也沒有很差,只是代碼比較繁瑣,倒不如使用模板來的爽快。測試

下面是測試代碼:spa

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test::getInstance().init();
    CSingletonTwo::getInstance().init();
    return a.exec();
}

下面是在Qt5.3.2上測試的輸出:線程

相關文章
相關標籤/搜索