单例模式简析
一、单例模式
     单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。
     特点就是多读单写。
函数简单实现:
class Singleton
{
public:
       static Singleton*GetInstance()//申明为static,可以由对象直接调用,不用用类调用
       {
              if (_sInstance == NULL)
              {
                     _sInstance = new Singleton;
              }
              return _sInstance;
       }
       void printf()
       {
              cout << _data << endl;
       }
protected:
       Singleton()
              :_data(0)
       {}
       //防拷贝,只申明不定义
       Singleton(Singleton&);
       Singleton&operator=(Singleton&);
       //指向实例的指针定义为静态私有,这样定义静态成员函数获取对象实例
       static Singleton* _sInstance;
private:
       int _data;
};
Singleton*Singleton::_sInstance = NULL;//初始化
int main()
{
       Singleton::GetInstance()->printf();
       return 0;
}

二、基于线程安全的改进
     若有两个线程同时访问单例模式获取对象的方法,thread1执行方法,第一次进入发现指针为NULL,在还没有new之前,thread2也进入,这样就不能保证只有一个对象被创建,且第二个创建的对象将第一个创建的对象覆盖
解决方法:
     1、懒汉模式
     调用对象时才产生实例对象
 
改进
     static Singleton*GetInstance()
       {
              if (_sInstance == NULL)//保证效率
              {
                     _mx.lock();//保证线程安全
                     if (_sInstance == NULL)
                     {
                           _sInstance = new Singleton;
                           //解法:RAII 2.用库函数的guard
                     }
                     _mx.unlock();
              }
              return _sInstance;
       }
     新增static成员对象
     static mutex _mx;
     在类外需要初始化
     mutex Singleton::_mx
    
     但是,这么做有会引入新的问题,即当发生new失败时,则会发生抛异常, 而抛异常则会导致死锁。
     解决方法:可以使用RAII,自动析构,guard
     static Singleton*GetInstance()
       {
              if (_sInstance == NULL)//保证效率
              {
                     lock_guard<mutex> lock(_mx);
                     if (_sInstance == NULL)
                     {
                           _sInstance = new Singleton;//new 有可能会抛异常,若抛异常则导致死锁,但是用lock_guard可以出作用域自动析构
                     }
              }
              return _sInstance;
       }
     2、饿汉模式
     最开始就创建对象
     既线程安全,又高效
     指针为静态,在main函数之前初始化,
class Singleton
{
public:
       static Singleton*GetInstance()
       {
              assert(_sInstance);
              
              return _sInstance;
       }
       void printf()
       {
              cout << _data << endl;
       }
protected:
       Singleton()
              :_data(0)
       {}
       //防拷贝,只申明不定义
       Singleton(Singleton&);
       Singleton&operator=(Singleton&);
       //指向实例的指针定义为静态私有,这样定义静态成员函数获取对象实例
       static Singleton* _sInstance;
private:
       int _data;
};
Singleton*Singleton::_sInstance = new Singleton;

三、关于面试题
1、定义一个类,只能在堆上生成对象
     
class A
{
public:
       A*GetObj()
       {
              return new A;
       }
private:
       A()
       {}
       A(const A&);
};
2、定义一个类,只能在栈上生成对象
     
class A
{
private:
       void*operator new (size_t);
       void operator delete(void *p);
       void*operator new[](size_t);
       void operator delete[](void *p);
private:
       int a;
};
阅读更多
个人分类: 数据结构
想对作者说点什么? 我来说一句

STL简析入门基础学习

2011年05月16日 61KB 下载

简析搜索引擎实现原理

2010年12月13日 535KB 下载

单例模式单例模式单例模式

2011年07月31日 467KB 下载

B2C电子商务推广方案简析

2011年12月11日 29KB 下载

Discuz!NT 缓存设计简析

2010年08月19日 103KB 下载

ThinkPHP2.1.0 RBAC类使用简析.chm

2011年09月13日 309KB 下载

研磨单例模式研磨单例模式

2010年12月15日 123KB 下载

单例模式(讲解单例模式)

2011年01月18日 317KB 下载

Java单例模式(DOC)

2009年10月21日 91KB 下载

没有更多推荐了,返回首页

不良信息举报

单例模式简析

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭