Qt实现简单的单例模式
单例模式十分的常见也很常用,Boost库中就有单例的泛型实现,Qt中,可以利用原子指针来实现一个单例模式:
1 class SingleTon{ 2 public: 3 static SingleTon &getInstance(void) 4 { 5 //双重检测加锁 6 if(!instance){ 7 QMutexLocker locker(&mutex); 8 if(!instance) 9 instance = new SingleTon; 10 } 11 return * instance; 12 } 13 private: 14 SingleTon(); 15 SingleTon(const SingleTon & ); 16 SingleTon & operator = (const SingleTon &); 17 QReadWriteLock internalMutex; 18 static QMutex mutex; 19 static QAtomicPointer<SingleTon> instance; 20 }; 21 22 //初始化静态变量 23 QMutex SingleTon::mutex; 24 QAtomicPointer<SingleTon> SingleTon::instance = 0;
在上面的单例中,除了原子锁之外,另外还提供了读写锁,以供在需要读(QReadLocker(&internalMutex))或者写(QWriteLock(&internalMutex))的成员函数中去使用。
上面的例子看起来好像没什么问题,但是实际上Qt提供的原子锁在乱序执行的情况下的时候提供的实际上并不是原子操作,下面对其做一些修改:
1 class SingleTon{ 2 public: 3 static SingleTon &getInstance(void) 4 { 5 #ifdef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE 6 if(!QAtomicPointer::isTestAndSetNative())//运行时进行检测 7 qDebug() << "Error: don's support TestAndSetNative!!!!!!" 8 #endif 9 //双重检测加锁 10 if(instance.testAndSetOrdered(0,0)){ 11 QMutexLocker locker(&mutex) 12 instance.testAndSetOrdered(0, new SingleTon); 13 } 14 return * instance; 15 } 16 private://下与上相同 17 SingleTon(); 18 SingleTon(const SingleTon &); 19 SingleTon & operator=(const SingleTon &); 20 QReadWriteLock internalMutex; 21 static QMutex mutex; 22 static QAtomicPointer<SingleTon> instance; 23 };
上面才是原子指针的正确使用方法。关于双重检测加锁的问题,可以见这篇文章。