单例九品--第七品

单例九品第七品

  • 上一品引入
  • 写在前边
  • 代码部分
  • 实现思路的评注与思考
  • 下一品的设计思考

上一品引入

第六品着重解决了因为链接顺序造成的未定义问题,通过强制对象完成编译期初始化和使用基本类型代替抽象类型,使得全局对象的缺省初始化从不平凡变为平凡初始化,从而解决了因翻译单元链接顺序不同造成的未定义问题。但是,因为初始化子类中的全局对象构造需要计数值的配合,正是计数值这种写法造成了多线程的安全问题,第六品的例子3可能会出现单例对象的过早销毁,从而因此程序崩溃的问题。
所以,第七品将会着重解决这个问题。

另外从第五品开始引入了指针,全局对象都变成了指针类型,第五品是智能指针和智能指针的拓展类,第六品为裸指针。指针与引用的区别就是,引用完成了对象的绑定就不会在改变绑定对象,就可以理解为是一个有固定指向的指针。但是指针的话,如果没有限定指向,是可以自由变更朝向的,这个问题就是第五品以后,将全局对象变为指针后引入的问题。但是这个问题不在本品中进行讨论,指针类型的全局对象存在被修改的问题,将在第八品中进行讨论。第七品只讨论第六品引入的线程安全问题。

写在前边

  • 基本思路
    • 为引用计数引入线程安全操作
  • 优点
    • 全局对象初始化/销毁多线程安全
  • 缺点
    • 指针有被修改的风险

代码部分

三个文件: sing.cpp main.cpp和sing.h

  • main.cpp
#include "sing.h"
static Sing::Init init;
auto singletonInst2 = singletonInst->val;int main(int argc, char** argv)
{std::cout << "get value: " << singletonInst2 << '\n';std::cout << singletonInst << std::endl;std::cout << singletonInst->val << std::endl;
}
  • sing.cpp
#include "sing.h"
#include <memory>
#include <iostream>Sing* singletonInst;   // 全局对象,但是是指针类型的对象,在main函数中可能会被修改,造成程序崩溃Sing::Init::Init()
{auto& count = Sing::Init::RefCount();auto ori = count.fetch_add(1);//返回的ori为count加1前的值if (ori == 0){singletonInst = new Sing();   // 全局对象访问点}
}Sing::Init::~Init()
{auto& count = Sing::Init::RefCount();auto ori = count.fetch_sub(1);//返回的ori为count减1前的值if (ori == 1){delete singletonInst;singletonInst = nullptr;}
}
  • sing.h
#pragma once
#include <atomic>
#include <iostream>class Sing
{
public:struct Init{Init();Init(const Init&) = delete;Init& operator= (const Init&) = delete;~Init();static std::atomic<unsigned>& RefCount(){static std::atomic<unsigned> singletonCount{ 0 };return singletonCount;}};private:Sing(){std::cout << "Sing construct\n";val = 100;}~Sing(){std::cout << "Sing destroy\n";}Sing(const Sing&) = delete;Sing& operator= (const Sing&) = delete;
public:int val;
};extern Sing* singletonInst;
  • output
    g++ -c main.cpp
    g++ -c sing.cpp
    g++ main.o sing.o -o ./ms
    g++ sing.o main.o -o ./sm
    两种链接顺序的结果都是
Sing construct
get value: 100
0x557949424eb0
100
Sing destroy

实现思路的评注与思考

  1. 这种实现方式使用静态初始化函数的方式完成std::atomic类型的引用计数值的构建,使用静态初始化函数的方式完成计数值singletonCount的初始化。

  2. 为什么使用std::atmoic完成singletonCount的定义?
    答: 1) std::amotic是个原子操作,用于实现原子操作。原子操作是在并发编程中用来确保多个线程在同一时间对共享数据的访问是安全的,不会发生竞态条件(race condition)的操作。2) 在多线程编程中,如果多个线程同时访问同一块内存区域,并且其中至少有一个线程对该内存区域进行写操作,就可能导致竞态条件。std::atomic 提供了一种机制来避免竞态条件,能够确保在单个原子操作中对共享变量进行读取、修改、写入等操作,从而保证这些操作的完整性。

  3. 使用静态初始化函数的方式完成计数值的初始化,同样会引入多线程安全的时间损失。如果在main函数中多个线程都调用RefCount函数(如果是第一次,就构建singletonCount对象。随后每次掉用这个函数,都不会构建新的,这是静态初始化的作用),那么每次都需要加锁,判断,解锁操作

  4. ==为什么使用sing类中的静态函数完成计数值singletonCount的定义,在之后每一次使用计数值的时候,再去调用接口Recount呐?这样也会引起多线程的时间消耗,就相当于构建了一个计数值到单例。这么设计也是从程序安全性和限制用户构建sing类的多个不同对象来设计的。具体怎么解释还没想好。待后续补充

  • 缺点
    全局对象是指针类型的对象,在main函数中可能会被修改,造成程序崩溃。全局对象改为指针类型,是在第四品的例子2到第五品的转换,为了解决第四品的例子2中因为翻译单元链接顺序导致的静态实例初始化灾难,从而在第五品中引入了指针类型的全局对象,并在初始化的时候控制对象的初始化,从而避免链接问题造成的未定义问题 [singletonInst.reset( new Sing)]。为了方便修改指针的指向

下一品的设计思考

第八品将解决全局对象为指针而引入的指针会被修改的风险

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

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

相关文章

全量知识系统问题及SmartChat给出的答复 之18 三个子系统 之1

Q56.全量 知识系统中的三个子系统 下是全量知识系统的三个子系统的内部需要的内容。请仔细阅读上述内容&#xff0c;先设计一段程序能表示上述信息中你能了解到的部分。 1、数据系统{ projection-语法 key-value }里程牌&#xff1a;数据及数据类型 区划技术板块&#xff1a;…

2024 年 AI 辅助研发发展与趋势研究

引言 这几年&#xff0c;人工智能&#xff08;AI&#xff09;技术火得不行&#xff0c;它渗透到了我们生活的方方面面。从帮助我们识别图片、理解语音&#xff0c;到推荐我们喜欢的内容&#xff0c;甚至自动驾驶汽车&#xff0c;AI都在大显身手。特别是在研发领域&#xff0c;…

软考笔记--软件可靠性设计

保障软件可靠性最有效、最经济、最重要的手段是在软件设计阶段采取措施进行可靠性控制。为了从根本上提高软件的可靠性&#xff0c;降低软件后期修改的成本和难度&#xff0c;人们提出了可靠性设计的概念。可靠性设计其实就是在常规软件设计中&#xff0c;应用各种方法和技术&a…

蓝桥杯倒计时 36天-DFS练习

文章目录 飞机降落仙境诅咒小怂爱水洼串变换 飞机降落 思路&#xff1a;贪心暴搜。 #include<bits/stdc.h>using namespace std; const int N 10; int t,n; //这题 N 比较小&#xff0c;可以用暴力搜搜复杂度是 TN*N! struct plane{int t,d,l; }p[N]; bool vis[N];//用…

基于springboot实现大学外卖管理系统项目【项目源码+论文说明】

基于springboot实现大学外卖管理系统演示 摘要 如今&#xff0c;信息化不断的高速发展&#xff0c;社会也跟着不断进步&#xff0c;现今的社会&#xff0c;各种工作都离不开信息化技术&#xff0c;更离不开电脑的管理。信息化技术也越来越渗透到各小型的企业和公司中&#xff…

C/C++蓝桥杯之REPEAT程序(较难)

问题描述&#xff1a; 附件prog.txt中是一个用某种语言编写的程序。 其中REPEAT k 表示一个次数为k的循环。循环控制的范围通过缩进表达&#xff0c;从次行开始连续的缩进比该行多的&#xff08;前面空白更长的&#xff09;为循环包含的内容。 例如&#xff1a; REPEAT 2; …

Java8 CompletableFuture异步编程-进阶篇

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前言 我们在前面文章讲解了CompletableFuture这个异步编程类的基本用法&#xff0c;…

Web Worker:JavaScript的后台任务解决方案

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux练习

作业要求&#xff1a; 自己安装linux环境&#xff0c;在每一个题目下贴执行命令和结果的截图 一、文件创建 1. 创建一个文件夹命名为mydir 2. 进入文件夹&#xff0c;创建一个文件&#xff0c;命名为myfile 3. 查看mydir文件夹下有哪些文件 答案获取&#xff1a; https:/…

SpringBoot项目没有启动按键

问题一&#xff1a; pom文件正常&#xff0c;但是springboot包报红&#xff0c;同时Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found报红 解决办法&#xff1a; 无法识别使用哪个版本的 spring-boot-maven-plugin 包 <build><plugins>&…

javase day01笔记

第一天课堂笔记 Java第三代高级语言中的面向对象的语言 b/s 浏览器/服务器c/s 客户端/服务端 1991年詹姆斯高斯林在sun公司开发的Java 常用的dos命令 磁盘操作系统&#xff1a;dos win &#xff0b; r -》 cmd dos命令 切换盘符&#xff1a;直接输入对应盘符目录操作&#x…

【排序算法】四个排序算法理论基础+Python代码:冒泡、插入、选择、快速排序

排序算法 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 常见的内部排序算法有&#xff1a;插入排序、希尔排序…

【C++进阶】哈希的应用 --- 布隆过滤器

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

面试准备不充分,被Java守护线程干懵了,面试官主打一个东西没用但你得会

写在开头 面试官&#xff1a;小伙子请聊一聊Java中的精灵线程&#xff1f; 我&#xff1a;什么&#xff1f;精灵线程&#xff1f;啥时候精灵线程&#xff1f; 面试官&#xff1a;精灵线程没听过&#xff1f;那守护线程呢&#xff1f; 我&#xff1a;守护线程知道&#xff0c;就…

计算机软件文档编制规范GB_T 8567-2006

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 计算机软件文档编制规范概述 计算机软件文档编制规范&#xff08;Specification for computer software documentation&#xff09; 由TC28&#xff08;全国信息技术标准化技…

面试 Java 并发编程八股文十问十答第二期

面试 Java 并发编程八股文十问十答第二期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;形成死锁的四个必要…

《HTTPS协议》

文章目录 一、什么是HTTPS协议二、理解关键字三、为什么要加密四、常见的加密方式1.对称加密2.非对称加密 五、如何进行加密&#xff1f;1.只使用对称加密2.只使用非对称加密3.双方都使用非对称加密4.使用对称加密非对称加密5.对称加密非对称加密CA证书认证5.1数据摘要&#xf…

GPT-4-turbo还是大家心中第一!Claude 3竞技场人类投票成绩出炉:仅居第三

Claude 3的竞技场排名终于揭晓了&#xff1a; 在仅仅3天的时间里&#xff0c;20000张投票使得排名的流量达到了前所未有的高度。 最后&#xff0c;Claude 3的"大杯"模型Opus以1233的分数赢得了胜利&#xff0c;成为了第一个能和GPT-4-Turbo匹敌的选手。 "中杯…

Flink 资源管理

文章目录 前言ResourceManager详解Slot 管理器SlotProviderSlot资源池Slot共享Slot共享的优点Slot 共享组与 Slot 共享管理器Slot资源申请 总结 前言 在Flink中&#xff0c;资源管理是一个核心组件&#xff0c;它负责分配和管理计算资源&#xff0c;以确保任务能够高效、稳定地…

Python使用Beautiful Soup及解析html获取元素并提取内容值

Python使用Beautiful Soup及解析html获取元素并提取内容值 1. 包括解析获取标题2. 根据标签及id获取所有元素3. 根据标签及class获取所有元素4. 获取元素下的标签的值5. 获取元素下的parent及child的元素的值参考 1. 包括解析获取标题 2. 根据标签及id获取所有元素 3. 根据标…