设计模式的理解:单例模式(Singleton)
单例模式使用的目的是 ①一个类只能初始化出一个对象 ②保证对象是线程安全的。
其做法:
1、将 构造函数 和拷贝构造函数 设置为私有 并将自身类的指针设置成静态成员,其函数方法也设置成静态方法。保证该类只创建一个对象
2、通过加锁的方式,对 对象访问加以限制
class Singleton { private:static Singleton * instance; Singleton (){} Singleton(const Singleton& other);public:static Singleton* getInstance() { if (instance == nullptr) { instance = new Singleton(); } return instance; }
}
以上在单线程中是可以满足一个类对象只会被初始化一次的条件。但是在多线程中 假如其中一个线程在执行 instance = new Singleton(); 语句前,而另外一个刚好进入 if 语句时,这个类就会被初始化两次。所以上述的编码方式时线程不安全的。
二、双重加锁
class Singleton { private:static Singleton * instance; Singleton (){} Singleton(const Singleton& other);public:static Singleton* getInstance() { if (instance == nullptr) { Lock lock;if(instance == nullptr){instance = new Singleton(); }} return instance; }
}
上述代码是双重锁机制,当一个线程先获取到锁的时候,第二个线程读锁时就会等待第一个锁初始化完对象后才继续执行。但是上述写法没有考虑到内存读写reorder不安全。
正常创建对象实例会走三步骤
1) 分配对象内存
2) 调用构造器,执行初始化
3) 将对象的引用赋值给变量。
然而在编译器优化等问题下,在实际可能的运行顺序是,先执行第三步再执行第二部,即先引用给对象再调用构造器。
如果
假如其中一个线程在执行 instance = new Singleton(); 语句时,分配完了内存,将对象将对象的引用赋值给变量,此时第二个线程判断 if (instance == nullptr) 不成立直接返回了一个还未初始化完的对象。那么就会造成线程不安全。这个创建对象的二三步骤乱序执行实际上叫重排序。
在JAVA ,C#中 ,新增了一个关键字volatile,在声明成员变量时 volatile static Singleton instance; 表示禁止 instance创建对象时重排序。
而在C++ 11版本的跨平台实现
//C++ 11版本之后的跨平台实现
// atomic c++11中提供的原子操作
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;/*
* std::atomic_thread_fence(std::memory_order_acquire);
* std::atomic_thread_fence(std::memory_order_release);
* 这两句话可以保证他们之间的语句不会发生乱序执行。
*/
Singleton* Singleton::getInstance() {Singleton* tmp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire);//获取内存fenceif (tmp == nullptr) {std::lock_guard<std::mutex> lock(m_mutex);tmp = m_instance.load(std::memory_order_relaxed);if (tmp == nullptr) {tmp = new Singleton;std::atomic_thread_fence(std::memory_order_release);//释放内存fencem_instance.store(tmp, std::memory_order_relaxed);}}return tmp;
}
或者有更简洁的C++写法,但在C++11版本前不支持。
class Singleton{
public:// 注意返回的是引用。static Singleton& getInstance(){static Singleton m_instance; //局部静态变量return m_instance;}
private:Singleton(); //私有构造函数,不允许使用者自己生成对象Singleton(const Singleton& other);
};
设计模式的理解:单例模式(Singleton)相关推荐
- HeaFirst设计模式-单件模式[单例模式](Singleton Pattern)
深入分析单件模式 本次主要介绍的内容有 单件模式 单线程下的单件模式实现 多线程下实现单件模式出现的问题分析 JMM内存模型 多线程下的单件模式实现的三种方式 这些内容,可以从最根本理解单例模式的代码 ...
- Net设计模式实例之单例模式( Singleton Pattern)
一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...
- JavaScript设计模式 Item 6 --单例模式Singleton
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器的window对象.在js开发中,单例模式的 ...
- java设计模式 单例_java设计模式一(单例模式singleton)
1 概述 如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式.这种情况在我们应用中经常碰到,例如缓存池.数据库连接池.线程池.一些应用服务实例等.在多线程环境中为了保证实例的唯一性其实并 ...
- 【设计模式笔记】单例模式Singleton Pattern
单例模式是比较简单的一个模式,项目中也经常用得到. 实现细节 将类的构造方法设置为私有的(private),通过个公有的(public)的方法来获取类的实例. 代码示例 public class Si ...
- 设计模式之略见一斑(单例模式singleton)
单例模式是属于比较常用的一例,一个类(class)在内存中只有一个实例. 常用方式如下: 第一种(饿汉式): public class Singleton { private Singleton(){ ...
- 《研磨设计模式》chap5 单例模式singleton
1. 模式介绍 1.1 饱汉式单例实现 public class Singleton {//定义一个变量来存储创建好的类实例 private static Singleton uniqueInstan ...
- JAVA设计模式Design Pattern→单例模式Singleton Pattern、工厂模式Factory Pattern、代理模式Proxy Pattern
私有化构造函数的类可以提供相应的 "接口"(一般就是静态方法)来返回自己的唯一实例供外部调用,像这样的确保只生成一个实例的模式被称作单例模式. 工厂模式,一个模型,用来大规模的生产 ...
- 设计模式 -- 单例模式(Singleton)
写在前面的话:读书破万卷,编码如有神 -------------------------------------------------------------------- 主要内容包括: 初始单例 ...
- 设计模式(21):创建型-单例模式(Singleton)
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
最新文章
- 基于vue2实现省市联动
- 利用Eclipse连接JDBC-(SQL Server2008)
- OpenCV gapi模块基本API的实例(附完整代码)
- 2019/01/29-Linux常用指令
- php的mktime,PHP mktime()函数获得本地时间戳
- foreach php 多重数组,PHP的foreach与多维数组
- 【论文】动态贝叶斯网络用于时序建模及动作分类
- 初识Quartz之CronTrigger
- JAVA-时间日期格式转换
- [渝粤教育] 西南科技大学 外国文学 在线考试复习资料
- PHP中级程序员常见面试题
- 梅特勒-托利多 TCS-35 电子台秤
- qt opengl 混合实现半透明
- 大气的品牌化妆品官网模板
- iPhone X测试烧屏软件,iPhone X烧屏测试,亮屏3天后才会发生
- Java英文技术网站
- 机器视觉为工业自动化打开“新视界”的大门
- 深化“智能二道门”建设,化工厂人员定位系统深度解析!
- 微信好友删除了怎么找回来?
- 聚观早报|网易开放暴雪游戏退款申请通道;鱼跃医疗回应被罚270万