Qt中实现单例模式(SingleTon),⼤约有3种办法
Qt中实现单例模式(SingleTon)
单例模式分为“饥汉”和“饿汉”两种版本,也正是线程安全问题使得原本简单的单例模式变得复杂。由于单例模式很常⽤,Boost库中有强⼤的泛型单例实现,我也利⽤Qt的原⼦指针QAtomicPointer来实现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();//禁⽌构造函数。
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.
修改版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操作保证在原⼦操作前和后的的内存访问
* 不会被重新排序。
*/
stAndSetOrdered(0, 0))//第⼀次检测
{
QMutexLocker locker(&mutex);//加互斥锁。
}
return *instance;
}
private:
SingleTon();//禁⽌构造函数。
SingleTon(const SingleTon &);//禁⽌拷贝构造函数。
SingleTon & operator=(const SingleTon &);//禁⽌赋值拷贝函数。QReadWriteLock internalMutex;//函数使⽤的读写锁。
static QMutex mutex;//实例互斥锁。
static QAtomicPointer<SingleTon> instance;/*!<;使⽤原⼦指针,默认初始化为0。*/ };
欢迎⼤家拍砖!
很久以前的⽂章了,实际上更Qt化的⽅法是直接⽤Q_GLOBAL_STATIC。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论