单例模式全面学习(C++版)
单例模式:用来创建独一无二的,只能够有一个实例的对象。 单例模式的结构是设计模式中最简单的,但是想要完全实现一个线程安全的单例模式还是有很多陷阱的,所以面试的时候属于一个常见的考点~
单例模式的应用场景:有一些对象其实只需要一个,比如:线程池,缓存,对话框,处理偏好设置和注册表的对象,日志对象,充当打印机,显卡等设备的驱动程序对象。这些对象只能够拥有一个实例,如果创建出了多个实例,就会导致一些程序的问题。程序的行为异常,资源使用的过量,或者导致不一致的结果。常用来管理共享的资源,比如数据库的连接或者线程池。
单例模式的类图非常简单,如下~,并且经典的实现也非常的简单。

class Singleton {
public:
static Singleton* getInstance();
//析构的时候释放资源~
~Singleton() {
if( (_instance != NULL)
delete _instance;
}
protected:
Singleton();
private:
static Singleton* _instance;
}
Singleton *Singleton::_instance = NULL;
Singleton* Singleton::getInstance() {
if( _instance == NULL) {
_instance = new Singleton();
}
return _instance;
}
经典的实现非常容易,但是存在一个问题,就是这个经典的实现非线程安全,多线程的情况下,这个单例模式的实现会出现问题~,如何解决呢?改进!
class Lock
{
private:
mutex mtex;
public:
Lock(mutex m) : mtex(m)
{
mtex.Lock();
}
~Lock()
{
mtex.Unlock();
}
};
class Singleton {
public:
static Singleton* getInstance();
//析构的时候释放资源~
~Singleton() {
if( (_instance != NULL)
delete _instance;
}
protected:
Singleton();
private:
static Singleton* _instance;
static mutex m;
}
Singleton *Singleton::_instance = NULL;
Singleton* Singleton::getInstance() {
//check 之前进行临界区加锁操作
Lock lock(m);
if( _instance == NULL) {
_instance = new Singleton();
}
return _instance;
}
线程安全保证的一种方法及为在check _instance == NULL 之前进行临界区加锁,如果已经有一个线程进入访问,其他线程必须等待,这样就能够保证多线程情况下实例的唯一!
but,互斥的同步会导致性能的降低,即使_instance已经不为空了,每次还是需要加锁,这样操作花费就比较多,性能必定比较差。
另外还有一些比较好的方法:
1.(非线程同步的方法)上面的操作均为一种lazy initialization的思想,及用到的时候在初始化,这样程序效率比较高,但是有一个另外比较好的方法可以采用是提前初始化,将_instance设置为static之后直接初始化为Singleton对象,每次只需要执行返回操作即可。
这样的话同样会导致问题,就是如果单例本来资源比较多,但是不需要创建那么早,就会消耗资源~。
class Singleton {
public:
static Singleton* getInstance();
//析构的时候释放资源~
~Singleton() {
delete _instance;
}
protected:
Singleton();
private:
static Singleton* _instance;
}
Singleton *Singleton::_instance = new Singleton();
Singleton* Singleton::getInstance() {
return _instance;
}
2.另外一种提升因为同步导致的性能变差的方法称为“双重检验加锁”。方法如下:
思路是只有在第一次创建的时候进行加锁,当_instance不为空的时候就不需要进行加锁的操作,这样就可以提升性能~
class Lock
{
private:
mutex mtex;
public:
Lock(mutex m) : mtex(m)
{
mtex.Lock();
}
~Lock()
{
mtex.Unlock();
}
};
class Singleton {
public:
static Singleton* getInstance();
//析构的时候释放资源~
~Singleton() {
if( (_instance != NULL)
delete _instance;
}
protected:
Singleton();
private:
static Singleton* _instance;
static mutex m;
} Singleton *Singleton::_instance = NULL;
Singleton* Singleton::getInstance() {
//check 之前进行临界区加锁操作
//双重检验加锁
if(_instance == NULL ) {
Lock lock(m);
if( _instance == NULL) {
_instance = new Singleton();
}
}
return _instance;
}
总之,小小单例模式问题还是挺多的,面试官喜欢问的一个问题~,因为还是有很多陷阱的。
单例模式全面学习(C++版)的更多相关文章
- Learning ROS for Robotics Programming - Second Edition(《ROS机器人编程学习-第二版》)
Learning ROS for Robotics Programming - Second Edition <ROS机器人编程学习-第二版> ----Your one-stop guid ...
- 软件开发常用设计模式—单例模式总结(c++版)
单例模式:就是只有一个实例. singleton pattern单例模式:确保某一个类在程序运行中只能生成一个实例,并提供一个访问它的全局访问点.这个类称为单例类.如一个工程中,数据库访问对象只有一个 ...
- c#.net单例模式的学习记录!
一. 单例(Singleton)模式 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其它对象提供这一实例. 单例模式应用: 每台计算机可以有若干个打印机 ...
- 单例模式总结(Java版)
1:懒汉的设计模式,在第一次调用的时候才完成相关的初始化操作 懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间.当然,如果一直没有人使用的话,那就不会创建实例 ...
- IOS 单例模式的学习
单例模式只能修改无法释放,直到程序结束. 我们下面一步一步来做一个单例模式程序 (1)单例一旦创建,是永远存在于内存中的,所以需要创建一个全局量 static MySingletonClass *sh ...
- HTML学习3---排版标记
上节,我们学习了boda常用的属性以及HTML的一些标记,但是图显示的效果却不是那么的好看. 原因就是没有排版好,我们这次使用居中来使这个页面更好看一点,顺便多加入几个别的标记. HTML排版标记 ( ...
- word2vec学习 spark版
参考资料: http://ir.dlut.edu.cn/NewsShow.aspx?ID=291 http://www.douban.com/note/298095260/ http://machin ...
- -sql语句练习50题(Mysql学习练习版)
–1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id) – –课 ...
- .NET单例模式快速学习应用
单例模式属于设计模式中最简单的一个模式,在实际应用中也非常广泛,但可能是受到各类教程的影响,看到很多实现方式仍然沿用Java的那一套,其实在.NET中可以用更简洁的实现方式. 一.知识点介绍 核心目标 ...
随机推荐
- mysql5.7 java读取乱码
一直很自信自己编码格式设置的都没有问题,以前就算遇到也都很快找到问题并解决.没想到掉进了5.7的坑里. 这段时间实习,大多做的都是.net+sqlserver,确实不用操心这些问题.主要还是各自默认编 ...
- Websphere下删除某个文件(ibm-partialapp-delete.props)
Websphere下删除某个文件(ibm-partialapp-delete.props)
- 禁止页面内按F5键进行刷新(扩展知识:禁止复制信息内容)
禁止页面内按F5键进行刷新: //禁止页面内按F5键进行刷新 function f_DisableF5Refresh(event) { var e = event || window.event; v ...
- 【QT学习】QT GUI应用程序的框架,文件分析
有几个名字,项目名,类名,界面对象名. 1.项目文件 项目名.pro(MyHelloQt.pro) 主要包括项目用到的模块,项目包含哪些源码文件,头文件,窗体文件,生成应用程序的名称. 由QT自动生成 ...
- in语句导致查询很慢
1.表A,表B,表C.其中A中的主键是B的外键,一对多的关系:B的主键是C的外键,一对多的关系.最终想查出所有符合条件的C. 原因:开发人员将A表数据先查出来,放到list中,然后用list作为in的 ...
- windows 环境内网超快同步 DFS
记录下: 在WINDOWS环境下,内网同步使用DFS可以超快实现文件同步,效果非常OK 纯粹记录下!
- Okhttp封装、网络层扩展
一.概述 首先在这里本片文章是以网络通信封装为主,而app开发首先重要就是网络通信,而如今主流的async.volley.okhttp等,阿么这么网络库怎样能做到更好封装.更好的切换,从而不影响业务层 ...
- 手机APP支付--整合支付宝支付控件
长话短说,本文根据支付宝官方说明文档,简单总结下,并且说明下开发过程碰到的问题以及该如何解决. 整合步骤: 1 登录商家服务网站,下载开发包,地址:https://b.alipay.com/order ...
- Go之对象拷贝
这里interface{}就相当于c#,java中的object, boy := util.Boy{util.Person{"Eric", 19, "boy"} ...
- MessageDigest类提供MD5或SHA等加密算法
MessageDigest可使用的加密方法有MD2\MD5\SHA-1\SHA-256\SHA-384\SHA-512,使用时候只替换相应参数值即可 MessageDigest md5 = Messa ...