C++多线程环境下的单例类对象创建

news2024/12/23 13:54:51

使用C++无锁编程实现多线程下的单例模式

贺志国
2023.8.1

一、尺寸较小的类单例对象创建

如果待创建的单例类SingletonForMultithread内包含的成员变量较少,整个类占用的内存空间较小,则可以使用如下方法来创建单例对象(如果类的尺寸较大则不允许,64位Linux系统默认栈的最大空间为8 MB,64位Windows系统默认栈的最大空间为1 MB):

class SmallSingletonForMultithread {
 public:
  static SmallSingletonForMultithread& GetInstance() {
    static SmallSingletonForMultithread instance;
    return instance;
  }
  
 private:
  SmallSingletonForMultithread() = default;
  ~SmallSingletonForMultithread() = default;

  SmallSingletonForMultithread(const SmallSingletonForMultithread&) = delete;
  SmallSingletonForMultithread& operator=(const SmallSingletonForMultithread&) = delete;
  SmallSingletonForMultithread(SmallSingletonForMultithread&&) = delete;
  SmallSingletonForMultithread& operator=(SmallSingletonForMultithread&&) = delete;
};

二、尺寸较大的类单例对象创建(要求显式调用销毁函数来避免内存泄漏)

在实际工作中,由于某些单例类的尺寸较大,静态变量存储栈区无法容纳该单例对象,因此无法使用上述方法来创建单例对象,这时需要使用new在堆区动态创建单例对象。为了避免多线程环境下对于单例对象的抢夺,可使用C++无锁编程来实现。需要付出的代价就是,最后一个调用者需要显式地调用销毁函数DestoryInstance来避免内存泄漏,示例代码如下所示:

#include <atomic>
#include <cassert>
#include <mutex>

class SingletonForMultithread {
 public:
  static SingletonForMultithread* GetInstance() {
    if (!instance_.load(std::memory_order_acquire)) {
      instance_.store(new SingletonForMultithread, std::memory_order_release);
    }

    return instance_.load(std::memory_order_relaxed);
  }

  static void DestoryInstance() {
    if (instance_.load(std::memory_order_acquire)) {
      auto* ptr = instance_.exchange(nullptr, std::memory_order_release);
      delete ptr;
      ptr = nullptr;
    }
  }

 private:
  SingletonForMultithread() = default;
  ~SingletonForMultithread() = default;

  SingletonForMultithread(const SingletonForMultithread&) = delete;
  SingletonForMultithread& operator=(const SingletonForMultithread&) = delete;
  SingletonForMultithread(SingletonForMultithread&&) = delete;
  SingletonForMultithread& operator=(SingletonForMultithread&&) = delete;

 private:
  static std::atomic<SingletonForMultithread*> instance_;
};

std::atomic<SingletonForMultithread*> SingletonForMultithread::instance_;

int main() {
  auto* singleton = SingletonForMultithread::GetInstance();
  assert(singleton != nullptr);

  singleton->DestoryInstance();

  return 0;
}

三、尺寸较大的类单例对象创建(不用显式调用销毁函数来避免内存泄漏)

很多时候,我们无法显式地调用销毁函数来避免内存泄漏,这时就可借助std::unique_ptr<T>std::call_once来实现,示例代码如下:

#include <cassert>
#include <memory>
#include <mutex>

class SingletonForMultithread {
 public:
  ~SingletonForMultithread() = default;

  static SingletonForMultithread* GetInstance() {
    static std::unique_ptr<SingletonForMultithread> instance;
    static std::once_flag only_once;

    std::call_once(only_once,
                   []() { instance.reset(new SingletonForMultithread); });

    return instance.get();
  }

 private:
  SingletonForMultithread() = default;

  SingletonForMultithread(const SingletonForMultithread&) = delete;
  SingletonForMultithread& operator=(const SingletonForMultithread&) = delete;
  SingletonForMultithread(SingletonForMultithread&&) = delete;
  SingletonForMultithread& operator=(SingletonForMultithread&&) = delete;
};

int main() {
  auto* singleton = SingletonForMultithread::GetInstance();
  assert(singleton != nullptr);

  return 0;
}

但我在Ubuntu 20.04系统上使用GCC 9.4.0似乎无法正常完成任务,会抛出异常,产生core dump,原因暂不详。
gcc
core dump

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

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

相关文章

【Linux命令200例】用rcp复制远程文件到本地

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜…

再添新证书!数据库云管平台 zCloud 与 OceanBase 完成产品兼容互认证

近日&#xff0c;云和恩墨 zCloud 数据库云管平台&#xff08;简称&#xff1a;zCloud&#xff09;与北京奥星贝斯科技有限公司&#xff08;简称&#xff1a;OceanBase&#xff09;完成产品兼容性互认证。本次测试结果表明&#xff1a;zCloud 具备对 OceanBase 的纳管、监控告警…

工业机器视觉系统开发流程简介

工业机器视觉系统的开发过程主要包括以下几个阶段&#xff1a; 需求分析和系统设计&#xff1a;与用户合作&#xff0c;明确系统的功能和性能需求&#xff0c;并设计系统的整体架构。 软、硬件选型&#xff1a;根据需求分析结果&#xff0c;选择适合的软、硬件设备&#xff0…

NASA和uAvionix在AAM测试场部署SkyLine C2指挥和控制服务

蒙大拿州比格福克和弗吉尼亚州汉普顿2023年07月28日——美国宇航局和uAvionix签署了一项太空法案协议&#xff0c;为城市环境中的无人机系统 (UAS)开发先进的超视距(BVLOS)指挥和控制(C2)技术。根据协议&#xff0c;NASA将与uAvionix合作&#xff0c;利用基于互联网的基础设施和…

qiankun框架vue3项目,子应用什么情况下会卸载

1.手动卸载 2.路由不匹配的时候&#xff0c;会自动卸载

STM32基础入门学习笔记:基础知识和理论 开发环境建立

文件目录&#xff1a; 一&#xff1a;基础知识和理论 1.ARM简介 2.STM32简介 3.STM32命名规范 4.STM32内部功能* 5.STM32接口定义 二&#xff1a;开发环境建立 1.开发板简介 2.ISP程序下载 3.最小系统电路 4.KEIL的安装 5.工程简介与调试流程 6.固件库的安装 7.编…

K3s vs K8s:轻量级对决 - 探索替代方案

在当今云原生应用的领域中&#xff0c;Kubernetes&#xff08;简称K8s&#xff09;已经成为了无可争议的领导者。然而&#xff0c;随着应用规模的不断增长&#xff0c;一些开发者和运维人员开始感受到了K8s的重量级特性所带来的挑战。为了解决这一问题&#xff0c;一个名为K3s的…

【数据结构与算法】单链表反转、双链表反转(含相关题型)

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 链表反转 1. 单链表反转 实现2. 双链表反转 实…

IT技术中最被人忽略的网络安全方向~超乎你的想象~

正文 听说网络工程师已成为IT人的最底层了&#xff1f;标题的问题是知乎上很多网工在提问的问题之一&#xff0c;总是在说网工行业已经不行了、网工成为最低成、网工已经没落了…… 今天针对这些问题&#xff0c;我们先明确一个看法&#xff1a; 这些都是对网工行业的误解。 …

Vue(五)git

Vue 三十二、git1.工具引入2.本地仓库3.远程仓库4.两人协作&#xff08;1&#xff09;非冲突&#xff08;2&#xff09;冲突&#xff08;3&#xff09;可视化 5.分支6.vue项目git注意 三十三、三十四、三十五、 三十二、git 1.工具引入 项目内容合并 传统&#xff1a;U盘&…

Twitter 劲敌 Threads,“魔改”了哪些 Python 技术栈?

Meta 创始人 Mark Zuckerberg 昨天在 Threads 上宣布&#xff0c;周三正式上线的 Threads 注册量已突破三千万。 Threads 是一个基本文本的社交应用&#xff0c;由 Instagram 团队开发。虽然它在功能上还无法真正取代 Twitter&#xff0c;但目前看来事实上已是 Twitter 的替代方…

前端学习--vue2--插槽

写在前面&#xff1a; 这个用法是在使用组件和创建组件中 文章目录 介绍简单使用多个插槽省写默认/后备内容作用域插槽常用实例Element-ui的el-table 废弃用法slot attributeslot-scope attribute 介绍 我们在定义一些组件的时候&#xff0c;由于组件内文字想要自定义&#…

minio-分布式文件存储系统

minio-分布式文件存储系统 minio的简介 MinIO基于Apache License v2.0开源协议的对象存储服务&#xff0c;可以做为云存储的解决方案用来保存海量的图片&#xff0c;视频&#xff0c;文档。由于采用Golang实现&#xff0c;服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置…

手机图片怎么转换成pdf?掌握这几种转换方法就够了

手机图片怎么转换成PDF&#xff1f;现在&#xff0c;随着手机拍照功能的不断升级&#xff0c;手机摄影已成为人们记录生活、工作的一种重要方式。但是&#xff0c;有时候需要将手机拍摄的图片转换成PDF&#xff0c;以便更好地编辑和分享。那么&#xff0c;如何将手机图片转换成…

vue3常用API之学习笔记

目录 一、setup函数 vue2与vue3变量区别 二、生命周期 三、reactive方法 四、ref方法 1、简介 2、使用 3、ref与reactive 4、获取标签元素或组件 五、toRef 1、简介 2、ref与toRef的区别 六、toRefs 七、shallowReactive 浅reactive 1、简介 2、shallowreactiv…

详解顺序表功能

前言 随着我们C语言的不断深入学习&#xff0c;我们要开始学习一点数据结构来增加我们的内功了&#xff0c;虽说现在很多高级语言的顺序表&#xff0c;链表等可以不用自己实现&#xff0c;但在C语言中是需要我们自己来实现的&#xff0c;这并不能说明C语言和其他语言比C语言很…

AP AUTOSAR在软件定义汽车生态系统中的角色

AP AUTOSAR在软件定义汽车生态系统中的角色 AP AUTOSAR是AUTOSAR(汽车开放系统架构)的最新版本之一,它是一种面向服务的软件平台,旨在满足未来汽车电子系统的需求,特别是高性能计算、高带宽通信、软件无线更新(OTA)等方面。 AP AUTOSAR在软件定义汽车生态系统中扮演着…

【以图搜图】Python实现根据图片批量匹配(查找)相似图片

目的&#xff1a;可以解决在本地实现根据图片查找相似图片的功能 背景&#xff1a;由于需要查找别人代码保存的图像的命名&#xff0c;但由于数据集是cifa10图像又小又多&#xff0c;所以直接找很费眼睛&#xff0c;所以实现用该代码根据图像查找图像&#xff0c;从而得到保存…

azure刷新令牌失效 The grant was issued for a different client id

博主在以msal-node这个认证库实现electron客户端混合h5授权登录后&#xff0c;在某一次访问令牌过期后并且通过已存储的刷新令牌获取新的访问令牌和刷新令牌时&#xff0c;在控制台日志看到了The grant was issued for a different client id报错。 Error refreshing token: Se…

产品经理都在收藏的10个原型设计工具!

在产品经理的设计工作中&#xff0c;原型工具是必不可少的&#xff0c;今天本文将会为大家分享8个好用的原型工具&#xff0c;助力产品经理实现高效设计&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一款优秀的原型工具&#xff0c;它可以在网页中直接运行并…