单例模式
使用场景:只有一个实例对象。
单例模式需要将默认构造函数声明为私有,这样就不会被外部new出来了,甚至可以将析构函数也声明为私有的,这样就只有自己能够删除自己了。单例模式分为饿汉模式和懒汉模式,定义如下:
class CSingleton
{
private:
CSingleton() //构造函数是私有的
{
}
static CSingleton *m_pInstance = NULL; //懒汉模式
//static CSinleton *m_pInstace = new CSinleton(); //饿汉模式
public:
//懒汉模式
static CSingleton * GetInstance()
{
if(m_pInstance == NULL) //判断是否第一次调用
m_pInstance = new CSingleton();
return m_pInstance;
}
//饿汉模式
//static CSingleton * GetInstance()
//{
// return m_pInstance;
//}
static CSingleton * RealeaseInstance()
{
if( m_pInstance != NULL)
{
delete m_pInstance;
m_pInstance = NULL;
}
}
};
用户访问唯一实例的方法只有GetInstance()成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的,所有GetInstance()之后的调用都返回相同实例的指针。
但是这里有一个问题,对于饿汉模式来说,多线程下就出现了问题:第一个线程进来判断m_pInstance == NULL, new出一个实例。这个时候第二个线程也进来了,判断的sInstance 也== NULL,然后也会 new 出一个实例,这样就new出了两个实例,显然这不是我们所要的单例模式了。因此,需要在代码中加锁:
static CSingleton * GetInstance()
{
lock();
if(m_pInstance == NULL) //判断是否第一次调用
m_pInstance = new CSingleton();
return m_pInstance;
unlock();
}
但这样写的话,会稍稍映像性能,因为每次判断是否为空都需要被锁定,如果有很多线程的话,就爱会造成大量线程的阻塞。于是大神们又提出了双重锁定:
static CSingleton * GetInstance()
{
if(m_pInstance ==NULL)
{
lock();
if(m_pInstance == NULL)
m_pInstance = new CSingleton();
unlock();
}
return m_pInstance;
}
这样只够极低的几率下,通过越过了if (m_pInstance== NULL)的线程才会有进入锁定临界区的可能性,这种几率还是比较低的,不会阻塞太多的线程,但为了防止一个线程进入临界区创建实例,另外的线程也进去临界区创建实例,又加上了一道防御if (m_pInstance== NULL),这样就确保不会重复创建了。
最后,推荐使用饿汉模式,安全,简单。
浙公网安备 33010602011771号