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上测试的输出:

  • 相关阅读:
    绝对路径和相对路径
    基本的文件操作
    Python2和3字符编码区别
    java开发两年了,连个java代理模式都摸不透,你怎么跳槽涨薪?
    【建议收藏】阿里P7总结的Spring注解笔记,把组件注册讲的明明白白
    面试官:你说你精通SpringBoot,你给我说一下类的自动装配吧
    面试BAT问的最多的27道MyBatis 面试题(含答案和思维导图总结)
    Springboot 框架整理,建议做开发的都看看,整理的比较详细!
    直面秋招!非科班生背水一战,最终拿下阿里等大厂offer!
    写的太细了!Spring MVC拦截器的应用,建议收藏再看!
  • 原文地址:https://www.cnblogs.com/huiz/p/8039389.html
Copyright © 2011-2022 走看看