小小及

单例模式

使用场景:只有一个实例对象。

单例模式需要将默认构造函数声明为私有,这样就不会被外部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),这样就确保不会重复创建了。

 

最后,推荐使用饿汉模式,安全,简单。

 

posted on 2018-08-02 10:56  小小及  阅读(135)  评论(0编辑  收藏  举报

导航