單例模式十分的常見也很常用,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 };
上面才是原子指針的正確使用方法。關於雙重檢測加鎖的問題,可以見這篇文章。