并发与多线程(4)单例设计模式共享数据分析 和call_once

news/2024/4/20 13:32:44/文章来源:https://blog.csdn.net/weixin_39354845/article/details/127609993

一、单例模式

顾名思义就是一个项目中的某个类只有一个对象,不允许在外面new 出第二个对象


#if 1  //单例模式  :class MyClass
{
private:MyClass(){}static  MyClass* m_instance; // public:static  MyClass* getInstance(){if (m_instance == NULL){m_instance = new MyClass();}return  m_instance;}void  func(){cout << "MyClass ::  func! \n";}
};//静态  在类外必须初始化
MyClass* MyClass::m_instance = NULL;
int main()
{MyClass* p = MyClass::getInstance();p->func();MyClass* p2 = MyClass::getInstance();p2->func();cout << "Hello World! \n";
}
#endif

从上面可以看出我们 p p2 都是同一个地址。,但是有个问题,这个单例对象如何来delete呢?

我们可以在这个单例模式中添加一个inner  class  ,用这个类来delete  我们的单例模式对象。

  // 这个类就是用来回收上面MyClass 的这个单例对象class  CGhuishou {public :~CGhuishou(){if (MyClass::m_instance){delete MyClass::m_instance;MyClass::m_instance = NULL;}}};

完整代码:


#if 1 //单例模式  : 懒汉式class MyClass
{
private:MyClass(){}static  MyClass* m_instance; // public:static  MyClass* getInstance(){if (m_instance == NULL){m_instance = new MyClass();static CGhuishou cg;}return  m_instance;}// 这个类就是用来回收上面MyClass 的这个单例对象class  CGhuishou {public :~CGhuishou(){if (MyClass::m_instance){delete MyClass::m_instance;MyClass::m_instance = NULL;}}};void  func(){cout << "MyClass ::  func! \n";}
};//静态  在类外必须初始化
MyClass* MyClass::m_instance = NULL;
int main()
{MyClass* p = MyClass::getInstance();p->func();MyClass* p2 = MyClass::getInstance();p2->func();cout << "Hello World! \n";
}
#endif

 二、单例模式的线程安全问题分析

上述代码,如有多个线程来同事new 对象,线程是不是安全呢??

void  mythread()
{cout << "mythread    ! \n";MyClass* p = MyClass::getInstance();cout << "mythread   is over   ! \n";
}// 两个线程
int main()
{// 两个线程的入口函数都是  mythread ,thread  t1(mythread);thread  t2(mythread);t1.join();t2.join();cout << "Hello World! \n";
}

这种情况就会导致线程不安全

我们可以加锁:

mutex mymutex;
class MyClass
{
private:MyClass(){}static  MyClass* m_instance; // public:static  MyClass* getInstance(){// 为了解决这种模式的线程安全问题,我们可在这里加锁unique_lock<mutex>  mylock(mymutex);if (m_instance == NULL){m_instance = new MyClass();static CGhuishou cg;}return  m_instance;}// 这个类就是用来回收上面MyClass 的这个单例对象class  CGhuishou{public:~CGhuishou(){if (MyClass::m_instance){delete MyClass::m_instance;MyClass::m_instance = NULL;}}};

但是这种方式执行效率太慢,在一般大数据中是不允许的,我么可以再次改进一下:

双重锁定:

static  MyClass* getInstance()
    {
        if (m_instance == NULL)
        {
         // 为了解决这种模式的线程安全问题,我们可在这里加锁
            unique_lock<mutex>  mylock(mymutex);
            if (m_instance == NULL)
            {
                m_instance = new MyClass();
                static CGhuishou cg;
            }
       }
        return  m_instanc

}

推荐的懒汉单例模式- 局部静态变量,是线程安全的:


#if 1   //推荐的懒汉式 模式  是线程安全的
class Singleton
{
public:~Singleton() {std::cout << "destructor called!" << std::endl;}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static Singleton& get_instance(){static Singleton instance;return instance;}
private:Singleton() {std::cout << "constructor called!" << std::endl;}
};int main(int argc, char* argv[])
{Singleton& instance_1 = Singleton::get_instance();Singleton& instance_2 = Singleton::get_instance();return 0;
}
#endif

注意在使用的时候需要声明单例的引用 Single& 才能获取对象

另外网上有人的实现返回指针而不是返回引用

static Singleton* get_instance(){static Singleton instance;return &instance;
}

这样做并不好,理由主要是无法避免用户使用delete instance导致对象被提前销毁。还是建议大家使用返回引用的方式。

C++ 单例模式总结与剖析 - 行者孙 - 博客园

三、call_once与单例模式

call_once的功能: 能保证函数a 只能调用一次,是具备互斥量能力的,而且更加高效。

使用:结合once_flag使用

  static  MyClass* getInstance()
    {
        call_once(gf,createInstance);// 如果多个线程都执行到这里的时候,第一个线程就会锁定,其他线程返回,gf 相当于是一般锁,这样也保证了线程的安全
        return  m_instance;
    }

#if 1  //call_once 的使用:
once_flag  gf;  // 定义一个once_flag 的标记
class MyClass
{static  void   createInstance()  // 这里是静态的  需注意{m_instance = new MyClass();}
private:MyClass(){}static  MyClass* m_instance; // public:static  MyClass* getInstance(){call_once(gf, createInstance);// 如果多个线程都执行到这里的时候,第一个线程就会锁定,其他线程返回,gf 相当于是一般锁,这样也保证了线程的安全return  m_instance;}void  func(){cout << "MyClass ::  func! \n";}
};void  mythread()
{cout << "mythread    ! \n";MyClass* p = MyClass::getInstance();cout << "mythread   is over   ! \n";
}//静态  在类外必须初始化
MyClass* MyClass::m_instance = NULL;
int main()
{// 两个线程的入口函数都是  mythread ,thread  t1(mythread);thread  t2(mythread);t1.join();t2.join();cout << "Hello World! \n";
}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_410092.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐一个.Net Core轻量级插件架构

今天给大家推荐一个开源插件架构。在介绍项目之前&#xff0c;我们了解下什么是插件架构&#xff0c;它的用处。 现有的软件开发中&#xff0c;业务越来越复杂&#xff0c;一些大型的项目版本一直在迭代&#xff0c;代码规模越来越大&#xff0c;涉及的人员也越来越多&#xf…

电子江湖里,女攻城狮到底是一种怎样的存在?

关于电子工程师这一角色&#xff0c;女生真的不能胜任么&#xff1f;我觉得不然&#xff01; 虽然说出身电子信息类的女生并不算多&#xff0c;去到职场中就职且能坚持下去的更是少之又少&#xff0c;毕竟理工科嘛&#xff0c;加上真实存在的行业歧视&#xff0c;想要靠近的女生…

学长教你学C-day5-C语言变量与数据类型

小韩是一个学习比较刻苦认真的学生&#xff0c;虽然老师上课进度刚讲到输入输出&#xff0c;但是小韩已经自学到C语言指针部分的内容了。但是进度太快的弊端就是有些东西很难消化吸收&#xff0c;这不就遇到了问题&#xff0c;来请教小刘&#xff1a;“学长&#xff0c;你说这个…

机器学习——聚类分析

文章目录聚类分析K-means算法K-中心算法DBSCAN算法聚类分析 K-means算法 算法简要步骤 随机选取K个样本点&#xff08;不一定来自样本数据&#xff09;作为初始的质心第一次迭代&#xff0c;将所有样本分配到这K个类中 对每个样本计算其到两个聚类中心的欧式距离&#xff08;…

2022年12个最佳WordPress备份插件比较

您是否正在寻找可靠的WordPress备份插件来定期备份您的网站&#xff1f; 备份就像您网站的安全网。每当您的网站因任何原因崩溃时&#xff0c;您都可以快速恢复您的网站。但是您需要确保您的备份具有最新的更改&#xff0c;否则您可能会丢失重要数据。一个好的备份插件将确保您…

艾美捷藻红蛋白RPE化学性质文献参考

艾美捷藻红蛋白RPE背景&#xff1a; R-藻红蛋白是从海藻&#xff08;甘紫菜或高氏肠枝藻&#xff09;分离的藻胆蛋白家族成员。从红藻中分离得到 R- 藻红蛋白(PE)。其主吸收峰位于565nm&#xff0c;次吸收峰位于496nm 和545nm。次级峰的相对显著性在不同种的 R-PE 中差异显著。…

前端开发学习之【Vue】-下

文章目录Vuex1.概述2.使用3.四个 map 方法4.模块化命名空间Vue Router1.SPA2.路由3.基本使用4.多级路由5.路由传参query参数6.命名路由7.路由传参params参数8.路由的props配置9.路由跳转方式10.缓存路由11. activated deactivated生命周期钩子12.路由守卫13.路由器的两种工作模…

极限多标签算法: FastXML 的解析

文章目录前言1.关于极限多标签 (XML: eXtreme multi-label Classification)1.1 流派1.2 评价指标2.FastXML2.1 FastXML的特点2.2 FastXML的局部性2.3 FastXML的拟合目标2.4 通过代码分析FastXML的拟合细节2.4.1 r\mathbf{r}^{}r的优化与拟合2.4.2 δ\deltaδ的优化与拟合 ---- …

知识图谱-命名实体-关系-免费标注工具-快速打标签-Python3

知识图谱-命名实体-关系-免费标注工具-快速打标签-Python3一、功能介绍1、代码文件夹结构2、运行环境3、自定义命名实体、关系模板4、导入文件5、选择自定义实体和关系文件6、文本标注7、撤销和取消标注8、导出和导出并退出系统9、导出文件后解析10、标注规范和KG规范11、系统提…

SQL学习二十、SQL高级特性

约束&#xff08;constraint&#xff09; 管理如何插入或处理数据库数据的规则。 DBMS 通过在数据库表上施加约束来实施引用完整性。 大多数约束是在 表定义中定义的&#xff0c;用 CREATE TABLE 或 ALTER TABLE 语句。 1、主键 &#xff08;PRIMARY KEY&#xff09; 主键是…

AMCL代码详解(六)amcl中的重采样

1.重采样判断 上一章讲述了amcl中如何根据激光观测更新粒子权重&#xff0c;当粒子更新完后amcl会需要根据程序判断是否需要进行重采样。这个判断在粒子观测更新权重后进行判断&#xff0c;代码在amcl_node.cpp中&#xff1a; if(!(resample_count_ % resample_interval_)){ p…

[GYCTF2020]Easyphp

尝试了一下万能密码不行&#xff0c;又到处翻了一下&#xff0c;扫目录结果又有www.zip 审计代码好久&#xff0c;序列化和sql结合的题还是第一次见&#xff0c;太菜了呀&#xff0c;花了很久时间才理解这个题 首先看到update.php&#xff0c;这个文件是最亮眼的&#xff0c;…

javascript 原生类 DOMParser 把 字符串格式的HTML文档源码 转换成 document DOM对象

文章目录IntroQADOMParser 在 console 的使用cheerio 在 node 项目中的使用Reference测试sumIntro 有一天我在写爬虫。 其实也说不上是爬虫&#xff0c;就是打开浏览器上网&#xff0c;觉得页面有些数据挺有意思&#xff0c;就打开开发者工具&#xff0c;在 Network/Console 中…

01.初识C语言1

一、前期准备 1.gitee网址&#xff08;代码托管网站&#xff09;&#xff1a;工作台 - Gitee.com Git教程 - 廖雪峰的官方网站 (liaoxuefeng.com) 用法&#xff1a; 1&#xff09;新建仓库 2&#xff09;随意勾选 3&#xff09;网络仓库构建完成 2.所学知识&#xff1a;计算…

【期末大作业】基于HTML+CSS+JavaScript网上订餐系统(23个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

Jetson Orin 平台单进程采集四路独立video调试记录

1. 概述 现在有4个摄像头, 如何捕获4个摄像头(/dev/video0 - video3)在一个进程像这样: 现在只能捕捉一个相机使用gst-launch如下: gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=1280,height=720 ! videoconvert ! video/x-raw,format=I420 ! xvimagesi…

《设计模式:可复用面向对象软件的基础》——行为模式(2)(笔记)

文章目录五、行为模式5.5 MEDIATOR(中介者)1.意图补充部分2.动机3.适用性4.结构5.参与者6.协作7.效果8.实现9.代码示例10.相关模式5.6 MEMENTO ( 备忘录)1.意图2.别名3.动机4.适用性5.结构6.参与者7.协作8.效果9.实现10.代码示例11.相关模式5.7 OBSERVER (观察者)1.意图2.别名3…

21.C++11

C11的官网&#xff1a;C11 - cppreference.com 1.C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于TC1主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&am…

Java语言实现猜数字小游戏

之前笔者在学习C语言的初级阶段&#xff0c;就已经实现了用C语言简单实现猜数字小游戏&#xff0c;既然笔者最近在学习Java的初级阶段&#xff0c;那么&#xff0c;也应该写一个Java语言实现的猜数字小游戏&#xff01;&#xff01; C语言实现猜数字小游戏&#xff1a;原文链接…

浏览器播放rtsp视频流:4、jsmpeg+go实现局域网下的rtsp视频流web端播放

文章目录1.前言2.资料准备3.兼容性及适用性说明4.jsmpeg架构5.基于以上架构的go方案可行性分析6.编译和结果展示&#xff08;编译坑点&#xff09;7.最后1.前言 之前的rtsp转webrtc的方案存在如下缺陷&#xff1a;1.只支持h264&#xff1b;2.受限于webrtc的理解难度以及搭建tu…