单例模式:用来创建独一无二的,只能够有一个实例的对象。 单例模式的结构是设计模式中最简单的,但是想要完全实现一个线程安全的单例模式还是有很多陷阱的,所以面试的时候属于一个常见的考点~

单例模式的应用场景:有一些对象其实只需要一个,比如:线程池,缓存,对话框,处理偏好设置和注册表的对象,日志对象,充当打印机,显卡等设备的驱动程序对象。这些对象只能够拥有一个实例,如果创建出了多个实例,就会导致一些程序的问题。程序的行为异常,资源使用的过量,或者导致不一致的结果。常用来管理共享的资源,比如数据库的连接或者线程池。

单例模式的类图非常简单,如下~,并且经典的实现也非常的简单。

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++版)的更多相关文章

  1. Learning ROS for Robotics Programming - Second Edition(《ROS机器人编程学习-第二版》)

    Learning ROS for Robotics Programming - Second Edition <ROS机器人编程学习-第二版> ----Your one-stop guid ...

  2. 软件开发常用设计模式—单例模式总结(c++版)

    单例模式:就是只有一个实例. singleton pattern单例模式:确保某一个类在程序运行中只能生成一个实例,并提供一个访问它的全局访问点.这个类称为单例类.如一个工程中,数据库访问对象只有一个 ...

  3. c#.net单例模式的学习记录!

    一. 单例(Singleton)模式 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其它对象提供这一实例. 单例模式应用: 每台计算机可以有若干个打印机 ...

  4. 单例模式总结(Java版)

    1:懒汉的设计模式,在第一次调用的时候才完成相关的初始化操作 懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间.当然,如果一直没有人使用的话,那就不会创建实例 ...

  5. IOS 单例模式的学习

    单例模式只能修改无法释放,直到程序结束. 我们下面一步一步来做一个单例模式程序 (1)单例一旦创建,是永远存在于内存中的,所以需要创建一个全局量 static MySingletonClass *sh ...

  6. HTML学习3---排版标记

    上节,我们学习了boda常用的属性以及HTML的一些标记,但是图显示的效果却不是那么的好看. 原因就是没有排版好,我们这次使用居中来使这个页面更好看一点,顺便多加入几个别的标记. HTML排版标记 ( ...

  7. word2vec学习 spark版

    参考资料: http://ir.dlut.edu.cn/NewsShow.aspx?ID=291 http://www.douban.com/note/298095260/ http://machin ...

  8. -sql语句练习50题(Mysql学习练习版)

    –1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id) – –课 ...

  9. .NET单例模式快速学习应用

    单例模式属于设计模式中最简单的一个模式,在实际应用中也非常广泛,但可能是受到各类教程的影响,看到很多实现方式仍然沿用Java的那一套,其实在.NET中可以用更简洁的实现方式. 一.知识点介绍 核心目标 ...

随机推荐

  1. Android图片编码机制深度解析(Bitmap,Skia,libJpeg)

    问题 工作中遇到了Android中有关图片压缩保存的问题,发现这个问题还挺深,而且网上资料比较有限,因此自己深入研究了一下,算是把这个问题自顶至下全部搞懂了,在此记录. 相关的几个问题如下: 1.An ...

  2. 非抢占式RCU实现(二),解释:为什么 RCU_NEXT_SIZE 宏值是4?

    参考:2.6.34 一个很奇怪的问题. 没有查找到为什么 RCU_NEXT_SIZE的值为4的原因(包括Documentation),主要是在rcu_state中定义了一个四级的list,感到很有意思 ...

  3. UITextField禁用掉编辑之后...

    某些UITextField只为了摆数据,还有响应点击,为了避免频繁出现键盘,所以把UITextField的人机交互(userInteractionEnabled)给关闭了 此时,给UITextFiel ...

  4. 【数据分析知识点】detailed table of contents

    Exploratory Data Analysis - Detailed Table of Contents http://www.itl.nist.gov/div898/handbook/eda/e ...

  5. Android学习之——ListView

    背景知识 ListView在Android应用中使用非常广泛,手机上必备的微博.网易新闻等,都使用了ListView.

  6. koa2入门学习

    koa模块 koa-route 路由 route.get("路径",路由函数) koa-static 静态资源加载     const serve(路径) koa-compose  ...

  7. Java 11正式发布,这几个逆天新特性教你写出更牛逼的代码

    就在前段时间,Oracle 官方宣布 Java 11 (18.9 LTS) 正式发布,可在生产环境中使用! 这无疑对我们来说是一大好的消息.作为一名java开发者来说,虽然又要去学习和了解java11 ...

  8. Python打包-py2exe

    上篇文章讲了pyinstaller,可以打包成包含Windows, Linux, Mac OS X, FreeBSD, Solaris and AIX等操作系统下的可执行文件,如果只针对Windows ...

  9. JVM知识点总览-中高级Java工程师面试必备

    对于搞开发的我们其实也是一样,现在流行的框架越来越多,封装的也越来越完善,各种框架可以搞定一切,几乎不用关注底层的实现,初级程序员只要熟悉基本的使用方法,便可以快速的开发上线:但对于高级程序员来讲,内 ...

  10. mysql执行SQL语句时报错:[Err] 3 - Error writing file '/tmp/MYP0G1B8' (Errcode: 28 - No space left on device)

    问题描述: 今天一同事在mysql中执行SQL语句的时候,报了/tmp空间不足的问题,报错如下: [SQL] SELECT f.prov as 字段1, MAX( CASE f.flag_name W ...