詳解 Qt 中實現(xiàn)單例模式
Qt 中實現(xiàn)單例模式是本文要介紹的內(nèi)容,不多說,先來看內(nèi)容。單例模式分為“饑漢”和“餓漢”兩種版本,也正是線程安全問題使得原本簡單的單例模式變得復(fù)雜。由于單例模式很常用,Boost庫中有強大的泛型單例實現(xiàn),我也利用Qt的原子指針QAtomicPointer來實現(xiàn)Qt中的單例模式:
- //.cpp
- class
- SingleTon{ public
- : /*! \brief 用于獲得SingleTon實例,使用單例模式。
- * \return SingleTon實例的引用。
- */
- static
- SingleTon &getInstance(void
- ) { //使用雙重檢測。
- if
- (!instance)//***次檢測
- { QMutexLocker locker(&mutex);//加互斥鎖。
- if
- (!instance)//第二次檢測。
- instance = new
- SingleTon; } return
- *instance; } private
- : SingleTon();//禁止構(gòu)造函數(shù)。
- SingleTon(const
- SingleTon &);//禁止拷貝構(gòu)造函數(shù)。
- SingleTon & operator
- =(const
- SingleTon &);//禁止賦值拷貝函數(shù)。
- QReadWriteLock internalMutex;//函數(shù)使用的讀寫鎖。
- static
- QMutex mutex;//實例互斥鎖。
- static
- QAtomicPointer<SingleTon> instance;/*!<使用原子指針,默認(rèn)初始化為0。*/
- };//靜態(tài)成員變量初始化。(在.cpp文件中)
QMutex SingleTon::mutex;QAtomicPointer<SingleTon> SingleTon::instance = 0;
雙重鎖檢測在C++中是安全的,另外提供了讀寫鎖,在修改單例數(shù)據(jù)的函數(shù)中使用寫鎖(QWriteLocker locker(&internalMutex););在讀取單例數(shù)據(jù)的函數(shù)中使用讀鎖(QReadLocker locker(&internalMutex);)。
之前沒考慮到亂序執(zhí)行問題,并且此前代碼有嚴(yán)重BUG,即對QAtomicPointer類型變量賦值操作不是原子操作,見官方文檔:
For convenience, QAtomicPointer provides pointer comparison, cast, dereference, and assignment operators. Note that these operators are not atomic.
修改代碼,使用testAndSetOrdered原子操作,并解決亂序執(zhí)行問題,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.
其中關(guān)于memory ordering,我轉(zhuǎn)過此帖:http://www.cnblogs.com/codingmylife/archive/2010/04/28/1722573.html
其中關(guān)于double checked locking,有此文:http://docs.huihoo.com/ace_tao/lifecycle.html
修改版SingleTon.cpp:
- //.cpp 一次修改版
- class
- SingleTon{ public
- : /*! \brief 用于獲得SingleTon實例,使用單例模式。
- * \return 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操作保證在原子操作前和后的的內(nèi)存訪問
- * 不會被重新排序。
- */
- if
- (instance.testAndSetOrdered(0, 0))//***次檢測
- { QMutexLocker locker(&mutex);//加互斥鎖。
- instance.testAndSetOrdered(0, new
- SingleTon);//第二次檢測。
- } return
- *instance; } private
- : SingleTon();//禁止構(gòu)造函數(shù)。
- SingleTon(const
- SingleTon &);//禁止拷貝構(gòu)造函數(shù)。
- SingleTon & operator
- =(const
- SingleTon &);//禁止賦值拷貝函數(shù)。
- QReadWriteLock internalMutex;//函數(shù)使用的讀寫鎖。
- static
- QMutex mutex;//實例互斥鎖。
- static
- QAtomicPointer<SingleTon> instance;/*!<使用原子指針,默認(rèn)初始化為0。*/
- };
小結(jié):詳解Qt 中實現(xiàn)單例模式的內(nèi)容介紹完了,希望本文對你有幫助!