• Qt中实现单例模式(SingleTon),大约有3种办法


    Qt中实现单例模式(SingleTon)
    单例模式分为“饥汉”和“饿汉”两种版本,也正是线程安全问题使得原本简单的单例模式变得复杂。由于单例模式很常用,Boost库中有强大的泛型单例实现,我也利用Qt的原子指针QAtomicPointer来实现Qt中的单例模式:

    //.cpp
    class SingleTon
    {

    public:
    /*! rief 用于获得SingleTon实例,使用单例模式。
    * eturn SingleTon实例的引用。
    */
    static SingleTon &getInstance(void)
    {
    //使用双重检测。

    if(!instance)//第一次检测
    {
    QMutexLocker locker(&mutex);//加互斥锁。

    if(!instance)//第二次检测。
    instance = new SingleTon;
    }

    return *instance;
    }

    private:
    SingleTon();//禁止构造函数。
    SingleTon(const SingleTon &);//禁止拷贝构造函数。
    SingleTon & operator=(const SingleTon &);//禁止赋值拷贝函数。

    QReadWriteLock internalMutex;//函数使用的读写锁。

    static QMutex mutex;//实例互斥锁。
    static QAtomicPointer<SingleTon> instance;/*!<使用原子指针,默认初始化为0。*/
    };
    //静态成员变量初始化。
    QMutex SingleTon::mutex;
    QAtomicPointer<SingleTon> SingleTon::instance = 0;
    双重锁检测在C++中是安全的,另外提供了读写锁,在修改单例数据的函数中使用写锁(QWriteLocker locker(&internalMutex););在读取单例数据的函数中使用读锁(QReadLocker locker(&internalMutex);)。

    之前没考虑到乱序执行问题,并且此前代码有严重BUG,即对QAtomicPointer类型变量赋值操作不是原子操作,见官方文档:

    For convenience, QAtomicPointer provides pointer comparison, cast, dereference, and assignment operators. Note that these operators are not atomic.

    修改代码,使用testAndSetOrdered原子操作,并解决乱序执行问题,testAndSetOrdered特性:

    This function uses ordered memory ordering semantics, which ensures that memory access before and after the atomic operation (in program order) may not be re-ordered.

    其中关于memory ordering,我转过此帖:http://www.cnblogs.com/codingmylife/archive/2010/04/28/1722573.html

    其中关于double checked locking,有此文:http://docs.huihoo.com/ace_tao/lifecycle.html

    修改版SingleTon.cpp:

    //.cpp 一次修改版
    class SingleTon
    {

    public:
    /*! rief 用于获得SingleTon实例,使用单例模式。
    * eturn SingleTon实例的引用。
    */
    static SingleTon &getInstance(void)
    {

    #ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
    if(!QAtomicPointer::isTestAndSetNative())//运行时检测
    qDebug() << "Error: TestAndSetNative not supported!";
    #endif

    //使用双重检测。

    /*! testAndSetOrders操作保证在原子操作前和后的的内存访问
    * 不会被重新排序。
    */
    if(instance.testAndSetOrdered(0, 0))//第一次检测
    {
    QMutexLocker locker(&mutex);//加互斥锁。

    instance.testAndSetOrdered(0, new SingleTon);//第二次检测。
    }

    return *instance;
    }

    private:
    SingleTon();//禁止构造函数。
    SingleTon(const SingleTon &);//禁止拷贝构造函数。
    SingleTon & operator=(const SingleTon &);//禁止赋值拷贝函数。

    QReadWriteLock internalMutex;//函数使用的读写锁。

    static QMutex mutex;//实例互斥锁。
    static QAtomicPointer<SingleTon> instance;/*!<使用原子指针,默认初始化为0。*/
    };
    欢迎大家拍砖!

    http://www.cnblogs.com/codingmylife/archive/2010/07/14/1777409.html

    看看 http://qt-project.org/wiki/Qt_thread-safe_singleton, 有很好的实现。

    很久以前的文章了,实际上更Qt化的方法是直接用Q_GLOBAL_STATIC。

  • 相关阅读:
    AFNetworking 3.0中调用[AFHTTPSessionManager manager]方法导致内存泄漏的解决办法
    UITableView自动计算cell高度并缓存
    iOS 10 应用内跳转到系统设置
    iOS 系统通知
    UITableViewDataSource TableView數據源協議
    HADOOP操作权限问题
    Echarts简单图表
    hadoop常见错误解决方法
    sqoop安装与简单实用
    hive的内置函数和自定义函数
  • 原文地址:https://www.cnblogs.com/findumars/p/6004311.html
Copyright © 2020-2023  润新知