关闭

单例模式简析

标签: 单例模式懒汉模式饿汉模式
174人阅读 评论(0) 收藏 举报
分类:
一、单例模式
     单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。
     特点就是多读单写。
函数简单实现:
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;
};
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

单例模式-析构函数的深入理解

singleton.md  单例模式 单件模式      保证一个类中仅有一个实例,并且提供一个访问他的全局访问点 a. 懒汉式:使用的时候才创建,多线程访问的时候线程不安全(双检锁) b. 饿汉式...
  • littesss
  • littesss
  • 2017-11-01 18:16
  • 169

全面解析单例模式

what why 单线程下的实现方式 懒汉式 多线程下的实现方式 饿汉式 懒汉式同步锁 双重校验锁 保证单例模式线程安全的另一种思路 思想 内部类实现单例 枚举类型实现单例 使用单例模式的风险和解决...
  • geekerhw
  • geekerhw
  • 2016-07-07 14:53
  • 1947

c++ 单例模式下的实例自动销毁(单例自动回收器)

前些日志看到一篇博文(见附加连接),关于C++单例模式下m_pinstance指向空间销毁问题,m_pInstance的手动销毁经常是一个头痛的问题,内存和资源泄露也是屡见不鲜,能否有一个方法,让实例...
  • roy1261
  • roy1261
  • 2016-05-16 16:17
  • 2137

单例模式与Android

单例模式(Singleton)一、  什么是单例模式单例模式,简单点来说就是设计一个类,使其在任何时候,最多只有一个实例,并提供一个访问这个实例的全局访问点。二、  为什么要单例在程序中的很多地方,只...
  • ljianhui
  • ljianhui
  • 2014-06-08 00:20
  • 11563

C#单例模式的几种实现方式

C#单例模式的几种实现方式
  • yanlovehan
  • yanlovehan
  • 2016-11-09 10:07
  • 2000

最简单的单例模式

如果一个类始终只能创建一个实例,则这个类被称为单例类。   在一些特殊的场景下,要求不允许自由创建该类的对象,而是只允许为该类创建一个对象。为了避免其他类自由创建该类的实例,我们把该类的构造器使...
  • u013700340
  • u013700340
  • 2014-04-03 20:14
  • 1324

设计模式之单例模式 (模板 智能指针 删除器) 实现【懒汉】

上一篇关于单例模式的实现 主要是基于DCL。但是多线程环境下并不能保证完全线程安全。 这篇文章实现的单例: 懒汉模式 的单例 基于模板和继承 线程安全 使用智能指针 防止内存泄露 效率相对较高 ...
  • u013575812
  • u013575812
  • 2016-03-29 15:05
  • 709

绝对不要在析构函数中释放单例-----这个至少3000元的bug让人蛋疼两三天

某系统在某特殊情况下, 会出现bug, 经我非常保守地估计, 这个bug的定位修改费用至少3000元, 这还不包括其他的费用。 脱离具体场景, 我来抽象出一个简单的模型, 示例代码如下: #inclu...
  • stpeace
  • stpeace
  • 2015-06-19 19:10
  • 2367

PHP设计模式之单例模式简单代码介绍

PHP设计模式之单例模式 单例模式是一种创建型模式,它会限制应用程序,使其只能创建某一特定类类型的一个单一的实例。举例来说,一个web站点将会需要一个数据库连接对象,但是应该有且只能有一个,因此我们...
  • u012675743
  • u012675743
  • 2015-04-09 18:10
  • 1380

单例模式简析

单例模式简析 使用场景 公司中同事做的小分享,整理一下。 使用场景 全局性的资源统一管理对象的创建和销毁开销比较大 实现基本思路 方案: 保证一个类只有一个实例,并提供...
  • javazcxg
  • javazcxg
  • 2017-07-30 11:29
  • 59
    个人资料
    • 访问:9412次
    • 积分:375
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条