设计模式(四) 单例模式 c++实现

单例模式介绍

单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

单例模式注意点 ##

1>只能实例化一个对象
2>构造函数私有化,这样在类外就不能另外new对象
2>多线程的时候注意加锁

优缺点

优点:.
1>由于在系统内存中只存在一个对象,因此可以 节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
2>避免对共享资源的多重占用.
缺点:
1>不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2>由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。

代码实现:

    class CSingleton  
    {  
    private:  
        CSingleton()   //构造函数是私有的  
        {  
        }  
        static CSingleton *m_pInstance;  
    public:  
        static CSingleton * GetInstance()  
        {  
            if(m_pInstance == NULL) {//判断是否是第一次调
                m_pInstance = new CSingleton();
            }  
            return m_pInstance;  
        }  
    };  

用户访问唯一实例的方法只有GetInstance()成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的。也就是说GetInstance的返回值是当这个函数首次被访问时被创建的。这是一种防弹设计——所有GetInstance()之后的调用都返回相同实例的指针

上诉代码在多线程的环境下却不行了,因为很可能两个线程同时运行到if (m_pInstance == NULL)这一句,导致可能会产生两个实例。于是就要在代码中加锁。

 static CSingleton * GetInstance()  
 {  
     Lock();
     if(m_pInstance == NULL) {//判断是否是第一次调
         m_pInstance = new CSingleton();
      }  
      Unlock();
      return m_pInstance;  
 }  

但这样写的话,有经验的人一眼就看出,这样会对性能有很大的影响,因为每次判断是否为空都需要被锁定,如果有很多线程的话,就爱会造成大量线程的阻塞。于是又有一种写法叫双重锁定。

 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),这样就确保不会重复创建了。

猜你喜欢

转载自blog.csdn.net/breakpoints_/article/details/80227878