C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)
C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)
- 应用场景
- 一、单例模式是什么?
- 二、使用步骤
- 1.UML图
- 2.代码实现
应用场景
通常我们在做通讯的时候,我们跟服务器数据交互,假如每次需要通讯交互我们都创建一个实例来通讯的话,那么其实这个通讯的交互可能是不安全的和不简洁的,因为多个通讯实例对象的交互在不同线程操作的时候会存在不同步的情况,同时多个实例的操作会增加交互流程的复杂度。或者再说,我们给系统做一个日志模块的时候,我们希望做到的当然是只有一个操作对象,可不想多个实例对象对同一个日志文件频繁的文件操作,这种的执行效果处理不佳,BUG会频繁找你。
一、单例模式是什么?
单例模式(Singleton)是保证一个类仅有一个实例,并且要提供一个访问这个类的全局访问点(提供访问接口函数)。
它同全局变量不同的是,全局变量可以被多个类使用,但是它不能防止被实例化多个对象,而单例模式的类对象可以保证没有被其他实例可以被创建,并且它可以提供一个访问该实例的方法。
二、使用步骤
1.UML图
2.代码实现
Singleton类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要是负责创建自己的唯一实例。
方法1:
#include <iostream>
using namespace std;class Singleton
{private:Singleton(){ m_Test = 520; }static Singleton *m_Instance; // 这里必须是静态对象int m_Test;public:static Singleton *GetInstance(){// 第一次调用GetInstance发现m_Instance是空指针的时候会先创建,这个唯一对象被创建// 接着后面再调用的话只是直接返回已创建的对象而已if (m_Instance == NULL ) m_Instance = new Singleton (); return m_Instance;}// 释放对象static void ReleaseInstance(){if (m_Instance != NULL ){delete m_Instance;m_Instance = NULL ;}}// 提供类对象操作接口int GetTest(){return m_Test;}};// 静态类对象的初始化方式
Singleton *Singleton ::m_Instance = NULL;int main(int argc , char *argv [])
{Singleton *pObj1= Singleton ::GetInstance();Singleton *pObj2= Singleton ::GetInstance();// 比较两次实例化后的对象的结果是实例相同if(pObj1 == pObj2)printf("two obj is same....");cout<<pObj1->GetTest()<<endl;cout<<pObj2->GetTest()<<endl;Singleton ::ReleaseInstance();return 0;
}
方法1应该是我们平时最简单常见的方式,但是这个方式有个问题就是,如果是多线程使用的话,多个线程同时,注意是同时访问Singleton类,调用GetInstance()方法,会有可能造成创建多个实例的。
方法2:
#include <iostream>
using namespace std;class Singleton
{private:Singleton(){ m_Test = 520; }static Singleton *m_Instance; // 这里必须是静态对象int m_Test;public:static Singleton *GetInstance(){// 加锁处理多线程问题Lock(); // C++没有直接的Lock操作,请使用其它库的Lock,比如Boost,此处仅为了演示说明if (m_Instance == NULL ) m_Instance = new Singleton (); UnLock();return m_Instance;}};// 静态类对象的初始化方式
Singleton *Singleton ::m_Instance = NULL;
这里lock是确保当一个线程位于代码的临界区时,另一个线程不会进入临界区,如果其他线程试图进入锁定的代码,则它将一直等待,直到
该对象被释放。
此处进行了两次m_Instance == NULL的判断,是借鉴了Java的单例模式实现时,使用的所谓的“双重锁定”机制。因为进行一次加锁和解锁是需要付出对应的代价的,而进行两次判断,就可以避免多次加锁与解锁操作,同时也保证了线程安全。如果进行大数据的操作,加锁操作将成为一个性能的瓶颈。
方法3:
#include <iostream>
using namespace std;class Singleton
{private:Singleton(){ m_Test = 520; }static Singleton *m_Instance; // 这里必须是静态对象int m_Test;public:static Singleton *GetInstance(){return const_cast <Singleton *>(m_Instance);}};// 静态类对象的初始化方式
const Singleton *Singleton ::m_Instance = new Singleton();
因为静态初始化在程序开始时,也就是进入主函数之前,由主线程以单线程方式完成了初始化,所以静态初始化实例保证了线程安全性。在性能要求比较高时,就可以使用这种方式,从而避免频繁的加锁和解锁造成的资源浪费。这种静态初始化的方式是在自己被加载时就将自己实例化,所以就被称之为饿汉式单例类,而原先方法1-2的处理方式是要在第一次被引用的时候,才会被自己实例化,所以我们也称之它为懒汉式单例类。
上述三种实现,都要考虑到实例的销毁,以下两种可以针对实例销毁的方式。,
方法4:
#include <iostream>
using namespace std;class Singleton
{private:Singleton(){ m_Test = 520; }static Singleton *m_Instance; // 这里必须是静态对象int m_Test;public:static Singleton *GetInstance(){static Singleton m_Instance;return &m_Instance;}
};
因为静态类对象不是通过指针创建,所以自然没有对应的delete。但是大多时候,我们可能会在new完一个对象之后,就会可能会对它进行释放,那么有没有一种方式能让它自动销毁,类似智能指针的方式呢。看下一个实现方式。
方法5:
#include <iostream>
using namespace std;class Singleton
{public:static Singleton *GetInstance(){return m_Instance;}int GetTest(){return m_Test;}private:Singleton(){ m_Test = 520; }static Singleton *m_Instance;int m_Test;// 创建释放类,用来自动销毁对象class GC{public :~GC(){// 释放类对象if (m_Instance != NULL ){cout<<"delete instance..." <<endl;delete m_Instance;m_Instance = NULL ;}}};static GC gc;
};// 初始化静态变量
Singleton *Singleton ::m_Instance = new Singleton();
Singleton ::GC Singleton ::gc;
C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)相关推荐
- 单例模式下的懒汉和饿汉模式
1 //单例模式---懒汉模式 2 public class Apple{ 3 //创建一个成员,在内存中只有一个拷贝 4 private static Apple apple = null; 5 p ...
- 单例模式的原理/懒汉模式/饿汉模式以及不同版本的单例模式程序
单例模式 单例模式定义 懒汉模式与饿汉模式 懒汉模式 饿汉模式 懒汉模式和饿汉模式的区别 懒汉模式的不同版本 版本一 版本二 版本三 版本四 单例模式定义 保证一个类仅有一个实例,并提供一个该实例的全 ...
- 设计模式——单例模式详解
单例 介绍 单例模式(Singleton Pattern)是Java中最基础最简单的设计模式之一,这种模式属于创建型模式,提供的就是一种创建对象的方式.这种模式中的单一类创建自己的对象,确保只有一 ...
- Java设计模式 - 单例模式详解(下)
单例模式引发相关整理 关联线程安全 在多线程下,懒汉式会有一定修改.当两个线程在if(null == instance)语句阻塞的时候,可能由两个线程进入创建实例,从而返回了两个对象.对此,我们可以加 ...
- iOS设计模式 ——单例模式详解以及严格单例模式注意点
一.我们常用的单例有哪些? [[UIApplication sharedApplication] statusBarStyle];//系统中的单例模式,通过它获取到状态栏的style [NSNotif ...
- 单例模式---懒汉模式与饿汉模式
单例模式:1)一个类只能创建一个实例2)构造函数和静态变量(加载类时即初始化)需为private3)get方法应该为public static,可供全局访问 //懒汉模式 public class l ...
- java设计模式之单例模式|单例模式之饿汉模式、懒汉模式、枚举方式|最详细的6种懒汉模式详解
目录 一.单例模式 二.饿汉模式和懒汉模式 1.饿汉模式,线程安全 2.懒汉模式 懒汉模式1,线程不安全(不常用) 懒汉模式2,线程安全(不常用) 懒汉模式3,线程安全,双重校验(不常用) 懒汉模式4 ...
- 大聪明教你学Java设计模式 | 第一篇:单例模式 (懒汉模式和饿汉模式)
前言 大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案.大聪明本着"独乐乐不如众乐乐"的宗旨与大家分享一下设计模 ...
- 设计模式——单例模式(懒汉模式,饿汉模式)
声明: 本博客参考C语言中文网和优秀博客总结得出: (1)C语言中文网链接 (2)优秀博客链接 单例模式的定义: 指一个类只有一个实例,且该类能自行创建这个实例的一种模式.例如,Windows 中只能 ...
最新文章
- MongoDB增加用户认证:增加用户、删除用户、修改用户密码、读写权限、只读权限...
- 无服务器架构正在蚕食基础设施
- dialog对话框初始化 mfc_MFC中Dialog初始化顺序
- [C++学习笔记](double*)malloc(n * sizeof(double));
- 如何快速理解递归——看这个就可以了
- Flume的Avro Sink和Avro Source研究之一: Avro Source
- 计算机部件动漫,因一个片段肝了整部番,电脑配件上榜,它满屏“虎狼之词”...
- mysql什么情况会刷脏页_mysql-刷脏页(12)
- 【计算机网络】——流量控制与可靠传输机制
- moead算法流程步骤_匈牙利算法原理与实现
- Chaarshanbegaan at Cafebazaar 水题
- mysql repalication_MYSQL数据库知识点总结
- 使用“npm init”初始化项目
- C#获取实体类属性名和值 | 遍历类对象
- 通信原理基础概念概述
- (附源码)Springboot校园万能跑系统 毕业设计 160934
- 腾讯云配置密钥使用putty登录 PuTTY实现Windows向Linux上传文件
- 为什么越长大越不想过生日
- 一只鸟就这样耍弄了一个人
- vscode 源代码管理窗口显示空白