单例模式——Singleton

GOF的《设计模式》中这样描述:保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能阻止你实例化多个对象。一个最好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

也就是说,很多时候我们需要全局的对象,如一个工程中,数据库访问对象只有一个,这时,可以考虑使用单例模式。单例模式比全局对象好还包括:单例类可以继承,如下例。

单例模式的关键点在于:构造函数私有,静态的GetInstance。

另外,在C++中必须注意内存的释放。C++、Java、C#中还要注意多线程时的同步问题。

ew plain

  1. #include <iostream.h>  
  2.   
  3. class CSingleton  
  4. {  
  5.     public:  
  6.     static CSingleton * GetInstance()  
  7.     {  
  8.         if(NULL == m_pInstance)  
  9.             m_pInstance = new CSingleton();  
  10.         return m_pInstance;  
  11.     }  
  12.     static void Release()   //必须,否则会导致内存泄露  
  13.     {  
  14.         if(NULL != m_pInstance)  
  15.         {  
  16.             delete m_pInstance;  
  17.             m_pInstance = NULL;  
  18.         }  
  19.     }  
  20.       
  21.     private:  
  22.         CSingleton()  
  23.         {  
  24.             cout<<"CSingleton"<<endl;  
  25.         };  
  26.         static CSingleton * m_pInstance;  
  27. };  
  28.   
  29. CSingleton* CSingleton::m_pInstance = NULL;  
  30.   
  31. class CSingleDraw:public CSingleton  
  32. {  
  33. public:  
  34.     static CSingleDraw* GetInstance()  
  35.     {  
  36.         if(NULL == m_pInstance)  
  37.             m_pInstance = new CSingleDraw();  
  38.         return (CSingleDraw*)m_pInstance;  
  39.     }  
  40. protected:  
  41.     CSingleDraw()  
  42.     {  
  43.         cout<<"CSingleDraw"<<endl;  
  44.     }  
  45. };  
  46.   
  47. int main()  
  48. {  
  49.     CSingleDraw* s1 = CSingleDraw::GetInstance();  
  50.     CSingleDraw* s2 = CSingleDraw::GetInstance();  
  51.     s2->Release();  
  52.     return 0;  
  53. }  

——————————————————————————

这个方法实现singleton不太好,会有多线程同步问题。
比如说一开始Singleton::instance为空。然后有线程A和线程B同时访问Singleton::GetInstance()。
有意思的是当任务A执行if (NULL == instance)这句时,刚判断好instance确实为空想调用new,或者时间可以再放款到正在执行new操作,但是还没有返回;要命的是调度器由于某些原因一下子剥夺了线程A的执行又去执行线程B了。线程B顺利地创建了一个instance实例,然后在某一时刻被调度器剥夺,再次执行线程A。OK,此时线程A从刚才的混沌中继续执行它的new Singleton()的操作,这样线程A所创建出来的就是另一个实例了。此时Singleton宣告破灭。

因此,能够迎合多线程,乃至多处理的单件处理可以用以下方式:

class Singleton   
{   
private:   
        static Singleton instance;   
        
        Singleton(void)   
        {   
        }   
        
public:                   
        
        static Singleton& GetInstance()   
        {
            return instance;
        }
};

Singleton Singleton::instance;


由于以上代码中,Singleton::instance在程序加载后由初始化程序建立,因此对于应用程序不会有多线程困扰。如果是在多处理器或多核处理器环境下还要注意Singleton的成员函数中的一些同步。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值