c++设计模式系列----单例模式(Singleton模式
单例模式是为了解决唯一对象实例问题而提出来的,许多时候整个系统只需要拥有一个全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。或者像是一个系统的管理员,由唯一一个管理员来管理各种数据的存取等。
实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。
在处理单例模式的时候,我们需要注意的是在多线程状态的时候,因为如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。
在一般情况下,我们是不需要用到多线程的,在单线程下的单例模式比较简单。代码如下:
///Singleton.h #ifndef SINGLETON_H
#define SINGLETON_H class Singleton {
public:
~Singleton();
static Singleton* getInstance();
protected:
Singleton();
private:
static Singleton* instance;
};
#endif
//Singleton.cpp #include "Singleton.h"
#include <iostream> using namespace std; Singleton::Singleton() {
cout << "Singleton..." << endl;
}
Singleton::~Singleton() {
cout << "~Singleton..." << endl;
} Singleton* Singleton::instance = NULL; Singleton* Singleton::getInstance() {
if (instance == NULL)
instance = new Singleton(); return instance;
}
下面我们来看看多线程,在高并发的环境下,上面的代码是不安全的,在高并发环境中,getInstance()方法可能返回多个指向不同的该类实例,如下图所示:

如果这两个线程按照上述的步骤来执行,不难看出,在时刻1和时刻2,由于还没有创建单例对象,Thread1和Theread2都会进入创建单例莫斯的代码块分别创建实例。在时刻3,Thread1创建了一个单例对象,但此时Thread2已经无法知道,它仍然会继续创建一个新的实例对象。于是这两个线程持有的实例并非为同一个。更为糟糕的是,在没有自动回收机制的语言平台如C++上运行这样的单例模式,因为我们认为创建了一个单例实例,忽略了其他线程所产生的对象,不会手动地去回收它们,会引起内存泄漏。因此我们要使用锁来保证只产生一个实例。
使用double-check来保证thread safety.但是如果处理大量数据时,该锁会成为严重的性能瓶颈。这种方法被称为懒汉模式。
class Singleton
{
public:
static Singleton* getInstance();
protected:
Singleton();
private:
static Singleton* instance;
}; Singleton* Singleton::m_instance = NULL; Singleton::Singleton() { } Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
还有一种方法,被称为饿汉模式,即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在以后仅返回此实例。
由静态初始化实例保证其线程安全性,因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。故在性能需求较高时,应使用这种模式可以避免频繁的锁争夺。
class Singleton
{
public:
static Singleton* getInstance() {
return m_instance;
} private:
static const Singleton* m_instance;
Singleton(){}
}; const Singleton* Singleton::m_instance = new Singleton;
c++设计模式系列----单例模式(Singleton模式的更多相关文章
- 设计模式之单例模式——Singleton
		
设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...
 - 设计模式(4) -- 单例模式(Singleton)
		
设计模式(4) -- 单例模式(Singleton) 试想一个读取配置文件的需求,创建完读取类后通过New一个类的实例来读取配置文件的内容,在系统运行期间,系统中会存在很多个该类的实例对象,也就是说 ...
 - 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
		
原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...
 - 【设计模式】单例模式-Singleton
		
[设计模式]单例模式-SingletonEnsure a class has only one instance, and provide a global point to access of it ...
 - 设计模式之——单例模式(Singleton)的常见应用场景
		
单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此 ...
 - [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表
		
所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理, ...
 - Java设计模式系列-抽象工厂模式
		
原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...
 - Java设计模式系列-工厂方法模式
		
原创文章,转载请标注出处:<Java设计模式系列-工厂方法模式> 一.概述 工厂,就是生产产品的地方. 在Java设计模式中使用工厂的概念,那就是生成对象的地方了. 本来直接就能创建的对象 ...
 - Java设计模式系列-装饰器模式
		
原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...
 - 设计模式一: 单例模式(Singleton)
		
简介 单例模式是属于创建型模式的一种(另外两种分别是结构型模式,行为型模式).是设计模式中最为简单的一种. 英文单词Singleton的数学含义是"有且仅有一个元素的集合". 从实 ...
 
随机推荐
- [洛谷P1341]无序字母对
			
题目大意:给一张无向图,找一条字典序最小的欧拉路径 题解:若图不连通或有两个以上的奇数点,则没有欧拉路径,可以$dfs$,在回溯时把这个节点加入答案 卡点:没有在回溯时加入答案,导致出现了欧拉路径没走 ...
 - MySQL中数据表的基本操纵
			
本文基于对国家863中部软件孵化器编著的<MySQL从入门到精通>一书的操作实践. 一.创建数据表 数据表属于数据库,在创建数据表之前,应该使用语句 USE 数据库名 指定操作是在那个 ...
 - C++中swap函数
			
本文是我用到swap函数时,对其产生好奇,所以结合网上有关博文写下的.个人水平有限,若有错误的地方,欢迎留言指出.谢谢! 一.通用的函数交换模板 template<class T> voi ...
 - HDU.2640 Queuing (矩阵快速幂)
			
HDU.2640 Queuing (矩阵快速幂) 题意分析 不妨令f为1,m为0,那么题目的意思为,求长度为n的01序列,求其中不含111或者101这样串的个数对M取模的值. 用F(n)表示串长为n的 ...
 - Flex 布局教程:语法篇 【转】
			
Flex 布局教程:语法篇 作者: 阮一峰 日期: 2015年7月10日 原文:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html 网 ...
 - #define与typedef
			
#define(宏定义)只是简单的字符串代换(原地扩展),它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了. typedef是为了增加可读性而为标识符另起的新名称(仅仅只是个别名), ...
 - 二叉树中和为某一值得路径 java实现
			
本题来自<剑指offer> 路径为从根节点到叶节点一条路径,路径经过的各节点数值之和等于某一给定数值,则打印路径上的节点 因为需要打印满足条件的路径节点信息和各节点之和,需要栈记录经过的节 ...
 - Java反转字符串的方式?
			
1. 将String转换成字符数组,再利用字符数组进行首尾调换. 2. 利用递归的方式,主要是:reverse(str.substring(1)) + str.charAt(0); 3. 虽然Stri ...
 - Java的四种引用?用到的场景?
			
在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分 ...
 - c# 计算时间差---天数
			
---处理两个时间相差的天数 测试数据:三个时间 DateTime dt1 = Convert.ToDateTime("2017-03-17 09:49:55.667"); Dat ...