单例模式使用的目的是 ①一个类只能初始化出一个对象 ②保证对象是线程安全的。

其做法:

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)相关推荐

  1. HeaFirst设计模式-单件模式[单例模式](Singleton Pattern)

    深入分析单件模式 本次主要介绍的内容有 单件模式 单线程下的单件模式实现 多线程下实现单件模式出现的问题分析 JMM内存模型 多线程下的单件模式实现的三种方式 这些内容,可以从最根本理解单例模式的代码 ...

  2. Net设计模式实例之单例模式( Singleton Pattern)

    一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...

  3. JavaScript设计模式 Item 6 --单例模式Singleton

    单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器的window对象.在js开发中,单例模式的 ...

  4. java设计模式 单例_java设计模式一(单例模式singleton)

    1 概述 如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式.这种情况在我们应用中经常碰到,例如缓存池.数据库连接池.线程池.一些应用服务实例等.在多线程环境中为了保证实例的唯一性其实并 ...

  5. 【设计模式笔记】单例模式Singleton Pattern

    单例模式是比较简单的一个模式,项目中也经常用得到. 实现细节 将类的构造方法设置为私有的(private),通过个公有的(public)的方法来获取类的实例. 代码示例 public class Si ...

  6. 设计模式之略见一斑(单例模式singleton)

    单例模式是属于比较常用的一例,一个类(class)在内存中只有一个实例. 常用方式如下: 第一种(饿汉式): public class Singleton { private Singleton(){ ...

  7. 《研磨设计模式》chap5 单例模式singleton

    1. 模式介绍 1.1 饱汉式单例实现 public class Singleton {//定义一个变量来存储创建好的类实例 private static Singleton uniqueInstan ...

  8. JAVA设计模式Design Pattern→单例模式Singleton Pattern、工厂模式Factory Pattern、代理模式Proxy Pattern

    私有化构造函数的类可以提供相应的 "接口"(一般就是静态方法)来返回自己的唯一实例供外部调用,像这样的确保只生成一个实例的模式被称作单例模式. 工厂模式,一个模型,用来大规模的生产 ...

  9. 设计模式 -- 单例模式(Singleton)

    写在前面的话:读书破万卷,编码如有神 -------------------------------------------------------------------- 主要内容包括: 初始单例 ...

  10. 设计模式(21):创建型-单例模式(Singleton)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

最新文章

  1. 基于vue2实现省市联动
  2. 利用Eclipse连接JDBC-(SQL Server2008)
  3. OpenCV gapi模块基本API的实例(附完整代码)
  4. 2019/01/29-Linux常用指令
  5. php的mktime,PHP mktime()函数获得本地时间戳
  6. foreach php 多重数组,PHP的foreach与多维数组
  7. 【论文】动态贝叶斯网络用于时序建模及动作分类
  8. 初识Quartz之CronTrigger
  9. JAVA-时间日期格式转换
  10. [渝粤教育] 西南科技大学 外国文学 在线考试复习资料
  11. PHP中级程序员常见面试题
  12. 梅特勒-托利多 TCS-35 电子台秤
  13. qt opengl 混合实现半透明
  14. 大气的品牌化妆品官网模板
  15. iPhone X测试烧屏软件,iPhone X烧屏测试,亮屏3天后才会发生
  16. Java英文技术网站
  17. 机器视觉为工业自动化打开“新视界”的大门
  18. 深化“智能二道门”建设,化工厂人员定位系统深度解析!
  19. 微信好友删除了怎么找回来?
  20. 聚观早报|网易开放暴雪游戏退款申请通道;鱼跃医疗回应被罚270万

热门文章

  1. 线程同步辅助类CyclicBarrier
  2. 《孵化皮克斯》读书第三天
  3. Shell之/bin/bash脚本的基础实战
  4. Newtonsoft.Json 的序列化与反序列化
  5. VMWare快捷键大全
  6. pagefile.sys
  7. Java程序访问Mysql Cluster
  8. Scrapy爬取姓名大全,看看那个名字最受父母青睐
  9. 【快速通关】Git快速上手gitee
  10. k8s pod资源限制策略:requests、limits配置示例