zoukankan      html  css  js  c++  java
  • 线程安全单例(用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上测试的输出:

  • 相关阅读:
    ThinkPHP 3.2.2 实现持久登录 ( 记住我 )
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 17 电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/huiz/p/8039389.html
Copyright © 2011-2022 走看看