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


   最近比較比較清閑,復習了下設計模式中的單例模式,對於單例模式,網上有很多實例,但是看來看去,很多感覺老是差點什么,當然也有比較多的寫的很好,所以決定自己動手練習下,順便記錄下,就當記筆記了。

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

  在單線程中,網上有很多懶漢模式,餓漢模式什么的,這些可以自己去百度,就說下我自己比較常用的一種,直接上代碼比較直觀:

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,但是在這基礎上加入了模板來實現,使用多種類型。我看網上也有使用繼承來達到單例適用多個類型,那樣也沒有不好,只是代碼比較繁瑣,倒不如使用模板來的爽快。

下面是測試代碼:

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM