线程安全单例(用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上测试的输出:

 

转载于:https://www.cnblogs.com/huiz/p/8039389.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程安全单例模式是一种在多线程环境下确保只有一个实例被创建的设计模式。在实际使用中,有时需要保证某个类的对象在整个应用程序中只能有一个实例存在,并且该实例在任何时候都能被访问和使用。 线程安全单例模板实现一般包含以下几个要点: 1. 构造器私有化:通过将类的构造函数私有化,可以防止在类外部直接实例化对象。 2. 静态成员对象:在类内部创建一个私有的静态成员对象,用于存储类的唯一实例。 3. 全局访问方法:通过提供一个公共的静态方法,来获取类的唯一实例。在该方法内部进行实例化操作,保证只有一个实例被创建。 4. 线程安全性:由于多线程环境下会有多个线程同时访问该方法,需要考虑线程安全问题。可以通过加锁机制,或者使用双重检查锁定(double-checked locking)来保证线程安全。 双重检查锁定是一种常用的实现方式,具体步骤如下: 1. 在全局访问方法内进行第一次判断,检查实例是否已经被创建。 2. 若实例为空,则进行同步锁定,防止其他线程同时进入。 3. 在同步块内再次检查实例是否为空,如果为空则进行实例化。 4. 返回实例。 这样可以确保在多线程环境下,只有一个实例被创建,同时保证访问的效率和线程安全性。 总之,线程安全单例模板是一种重要的设计模式,它可以保证在多线程环境下只有一个实例存在,并且正常进行访问。通过适当的加锁机制,可以确保线程安全性,保护对象的一致性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值