C++单例模式如何实现 线程安全版本与双重检查锁定

c++++中,线程安全的单例模式推荐使用局部静态变量实现,因为c++11保证了静态局部变量初始化的线程安全性,该方法无需手动加锁、代码简洁且自动管理生命周期;若需延迟初始化或传参构造,可采用双重检查锁定结合std::mutex和智能指针的方式,通过外层if减少锁竞争,内层if确保唯一实例创建,利用std::unique_ptr或std::shared_ptr避免内存泄漏;需注意双重检查中两次判空缺一不可,防止竞态条件和性能下降,同时避免裸new和手动delete,优先使用raii机制管理资源,确保在多线程环境下安全可靠地创建唯一实例。

C++单例模式如何实现 线程安全版本与双重检查锁定

在C++中,单例模式(Singleton Pattern)是一种常见的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。在多线程环境下,必须保证单例的构造是线程安全的。双重检查锁定(Double-Checked Locking Pattern, DCLP)是一种常用的实现方式,但需要小心处理以避免竞态条件。

下面介绍如何实现一个线程安全的单例模式,重点讲解双重检查锁定的正确写法。

1. 懒汉式 + 双重检查锁定(C++11 及以后推荐写法)

从 C++11 开始,标准引入了静态局部变量的线程安全性保证,这使得实现线程安全单例变得非常简单。但如果你仍想使用双重检查锁定(比如需要延迟初始化且不依赖静态变量),可以如下实现:

立即学习“C++免费学习笔记(深入)”;

#include class Singleton {public:    // 获取单例实例    static Singleton* getInstance() {        // 第一次检查:避免不必要的加锁        if (instance == nullptr) {            std::lock_guard lock(mutex_);            // 第二次检查:确保只有一个线程创建实例            if (instance == nullptr) {                instance = new Singleton();            }        }        return instance;    }    // 禁用拷贝构造和赋值    Singleton(const Singleton&) = delete;    Singleton& operator=(const Singleton&) = delete;private:    Singleton() = default;  // 私有构造函数    static Singleton* instance;    static std::mutex mutex_;};// 静态成员定义Singleton* Singleton::instance = nullptr;std::mutex Singleton::mutex_;

关键点说明:

双重检查:外层

if

避免每次调用都加锁,提高性能。mutex 保护:确保多线程下只有一个线程能进入创建实例的代码块。new 动态分配:注意需要手动管理内存,或结合智能指针。

⚠️ 注意:在 C++11 之前,这种写法可能因为内存模型问题存在风险(如指令重排导致返回未完全构造的对象)。但在 C++11 及以后,只要使用 std::mutex,配合编译器的内存屏障,是安全的。

2. 更推荐的线程安全实现:局部静态变量(Meyers Singleton)

C++11 标准规定:函数内的静态局部变量初始化是线程安全的。这是最简洁、最安全的单例实现方式。

class Singleton {public:    static Singleton& getInstance() {        static Singleton instance;  // 线程安全,C++11 起保证        return instance;    }    Singleton(const Singleton&) = delete;    Singleton& operator=(const Singleton&) = delete;private:    Singleton() = default;};

优点:

无需手动加锁,编译器自动保证线程安全。自动析构(由运行时管理),避免内存泄漏。代码简洁,不易出错。

缺点:

实例在第一次调用

getInstance()

时创建,但具体时机由运行时控制(不过这通常不是问题)。无法传参构造(如果需要参数初始化,此方法受限)。

3. 使用智能指针 + 双重检查锁定(支持手动控制生命周期)

如果你需要动态创建且希望自动管理内存,可以使用

std::unique_ptr

std::shared_ptr

#include #include class Singleton {public:    static Singleton& getInstance() {        if (!instance) {            std::lock_guard lock(mutex_);            if (!instance) {                instance = std::make_unique();            }        }        return *instance;    }    Singleton(const Singleton&) = delete;    Singleton& operator=(const Singleton&) = delete;private:    Singleton() = default;    static std::unique_ptr instance;    static std::mutex mutex_;};std::unique_ptr Singleton::instance = nullptr;std::mutex Singleton::mutex_;

注意:返回的是引用,但内部用指针管理。析构仍需注意,

unique_ptr

在程序结束时会自动释放。

4. 常见误区与注意事项

不要忽略第二次检查:如果去掉内层

if

,会导致每次加锁,性能下降。不要在没有锁的情况下直接使用

new

:可能多个线程同时创建实例。避免指令重排问题:在老式编译器中,

new

包含分配内存、调用构造函数、赋值给指针三个步骤,可能被重排。C++11 的

mutex

atomic

能避免这个问题。C++11 起,局部静态变量是安全的:优先使用 Meyers Singleton。

总结

推荐写法:使用函数内静态变量(Meyers Singleton),简洁且线程安全。需要延迟初始化或传参:使用双重检查锁定 +

std::mutex

+ 智能指针。避免裸

new

和手动

delete

:尽量用 RAII 和智能指针管理资源。

基本上就这些,不复杂但容易忽略细节。

以上就是C++单例模式如何实现 线程安全版本与双重检查锁定的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1471794.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
析构函数什么时候调用 资源释放时机分析
上一篇 2025年12月18日 19:07:35
异常处理性能影响大吗 零成本异常机制解析
下一篇 2025年12月18日 19:07:46

相关推荐

  • 如何使用Composer解决PHP类中自动添加Trait的难题?kkszymanowski/traitor库助你一臂之力

    最近在开发一个大型 PHP 项目时,我遇到了一个棘手的问题:需要将多个 Trait 动态添加到已有的类中。手动修改代码不仅耗时,而且容易出错,尤其是当你需要处理文件格式和确保 Trait 的正确位置时。经过一番搜索,我找到了 kkszymanowski/traitor 这个库,它通过 Compose…

    用户投稿 2026年8月28日
    000
  • MySQL索引原理与实战优化_提升查询性能的关键技术解析

    MySQL索引原理与实战优化_提升查询性能的关键技术解析MySQL索引原理与实战优化_提升查询性能的关键技术解析MySQL索引原理与实战优化_提升查询性能的关键技术解析MySQL索引原理与实战优化_提升查询性能的关键技术解析

    mysql索引类型包括b-tree、哈希、全文索引等,适用于不同查询场景。1.b-tree索引以树状结构存储数据,适合范围查询和排序;2.哈希索引适用于等值查询,但不支持范围查询;3.全文索引用于文本搜索。选择索引需考虑查询需求、数据类型及维护成本。索引失效常见原因包括使用函数、表达式、or条件不当…

    2026年8月28日 用户投稿
    100
  • 一加Ace 6系列曝光:骁龙8至尊下放+全新次旗舰芯

    今年第二季度,一加陆续推出了包括一加13t、一加ace 5至尊版以及一加ace 5竞速版在内的多款新机。据一加中国区总裁李杰介绍,在618大促期间,一加手机整体销量同比增长达到50%,成为行业增长最快的厂商之一!而近日,有消息显示,一加ace 6系列已经进入筹备阶段。 结合此前发布的一加Ace 5系…

    2026年8月28日
    000
  • 怎样在 Workerman 中集成 Redis,实现缓存与消息队列功能?

    在 workerman 中集成 redis 可以实现缓存和消息队列功能。1) 通过 php 的 redis 扩展建立连接。2) 使用 redis 作为缓存层,减少数据库查询次数。3) 利用 redis 实现消息队列,处理异步任务,提升系统并发能力。 引言 Workerman 作为一个高性能的 PHP…

    2026年8月28日
    000
  • 在 Yii 项目里,数据库迁移工具怎么正确使用?

    在 yii 项目中使用数据库迁移工具的步骤包括:1. 创建迁移文件,使用 yii migrate/create 命令;2. 应用迁移,使用 yii migrate 命令;3. 回滚迁移,使用 yii migrate/down 命令。通过这些步骤,你可以管理数据库结构变更,确保开发、测试和生产环境的一…

    2026年8月28日
    000
  • 内网横向移动:Kerberos认证与(哈希)票据传递攻击

    在上一节《内网横向移动:获取域内单机密码与hash》中,我们探讨了如何在内网渗透中获取主机的密码和哈希值。获取哈希后,我们可以尝试破解,如果破解失败,我们可以利用这些哈希通过pth、ptt等攻击方式继续进行内网的横向渗透,这就是我们接下来要讨论的内容。 本节,我们将详细讲解横向渗透中的Kerbero…

    2026年8月28日
    000
  • Epic已免费赠送超500款游戏 你领取了多少款?

    epic games于2018年12月正式上线epic游戏商城,并自此开始持续为玩家提供免费游戏。几乎每星期都有新的免费游戏开放领取,涵盖多种类型,从休闲小游戏到如《给他爱5》这样的热门大作均有涉及。 最近,Reddit论坛用户antonio_mas发布了一项统计结果:自2018年首次送出免费游戏《…

    2026年8月28日
    000
  • ThinkPHP 数据库连接与查询构造器实战

    在 thinkphp 中进行数据库操作的方法包括:1. 通过配置文件和 db 类连接数据库;2. 使用查询构造器构建 sql 查询;3. 执行 crud 操作;4. 进行关联查询;5. 调试和优化查询性能;6. 应用性能优化策略和最佳实践。 引言 在当今的 Web 开发领域,ThinkPHP 作为一…

    2026年8月28日
    000
  • kernel32.dll下载与安装指南 快速解决DLL缺失问题

    kernel32.dll下载与安装指南 快速解决DLL缺失问题kernel32.dll下载与安装指南 快速解决DLL缺失问题kernel32.dll下载与安装指南 快速解决DLL缺失问题kernel32.dll下载与安装指南 快速解决DLL缺失问题

    在使用windows操作系统时,有些用户可能会碰到程序启动时报错“无法找到kernel32.dll”或提示“kernel32.dll文件丢失”的问题。这类错误通常由系统文件损坏、病毒入侵或软件之间的冲突引起。下面为大家整理了几种有效的修复方法,一起来看看如何解决! 方法1:利用系统内置工具进行修复 …

    2026年8月28日 用户投稿
    000
  • Bing聊天更新:图像识别功能正式上线,提供智能解读!

    微软的Bing聊天即将迎来一次重要升级,在桌面端新增了一项令人兴奋的图像识别功能,这将彻底革新我们与图片交互的方式。此功能融入了OpenAI的ChatGPT-4视觉模型,具备精准识别并解析图像内容的能力,并且会通过丰富的示例为我们详细阐述。 当前,微软正面向全球部分用户试行Bing聊天的视觉功能。完…

    2026年8月28日
    100
  • Workerman 服务器 CPU 使用率过高,怎么进行性能调优?

    要降低 workerman 服务器的 cpu 使用率,可以采取以下措施:1. 简化业务逻辑,减少不必要的计算和 i/o 操作。2. 使用异步处理,将耗时任务放到异步队列中。3. 实施缓存机制,减少数据库查询次数。4. 配置负载均衡,避免单台服务器过载。通过这些方法,可以有效降低 cpu 使用率,提升…

    2026年8月28日
    100
  • Yii2 实现邮件发送功能的详细步骤

    在 yii2 中实现邮件发送功能需要以下步骤:1. 在配置文件中设置 mailer 组件,2. 使用 yii::$app->mailer->compose() 方法发送邮件。yii2 通过 yiiswiftmailermailer 类和 swift mailer 库简化了邮件发送过程,支…

    2026年8月28日
    000
  • MWC 3月3日开展 聚焦6G、生成式AI等

    2025世界移动通讯大会(mwc 2025)即将在3月3日至6日于西班牙巴塞隆纳盛大举办,今年主题为“converge. connect. create(融合、连结、创造)”,聚焦6g、生成式ai等技术,预计将吸引来自全球近2,700家企业、逾10万名与会者参与;国内科技大厂联发科(2454)、和硕…

    2026年8月28日
    000
  • Spring Boot集成MyBatis时,yml配置正确却找不到Mapper接口怎么办?

    Spring Boot整合MyBatis:Mapper接口扫描配置详解及疑难解答 在使用Spring Boot集成MyBatis时,一个常见问题是:yml配置文件明明正确配置了MyBatis,却仍然报错找不到对应的Mapper接口。本文将深入分析此问题,并提供有效的解决方法。 问题描述: 许多开发者…

    2026年8月28日
    000
  • SNK今年国内首个线下展!即将亮相北京核聚变

    SNK今年国内首个线下展!即将亮相北京核聚变SNK今年国内首个线下展!即将亮相北京核聚变SNK今年国内首个线下展!即将亮相北京核聚变SNK今年国内首个线下展!即将亮相北京核聚变

    snk今年国内首个线下展会重磅来袭!即将登陆北京核聚变 6月28日至29日,株式会社SNK将出席“核聚变游戏嘉年华2025北京站”,亮相首钢国际会展中心A1馆A11展位,与广大玩家热情互动!现场不仅有SCS 2025第一赛段决赛的激烈对决,还将公布EWC直通选手名单,并带来《饿狼传说:群狼之城》《拳…

    2026年8月28日 用户投稿
    000
  • 传软银正洽谈融资160亿美元专门投资人工智能

    ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 消息人士透露,日本软银集团正与多家银行商谈,寻求160亿美元贷款,以加大对人工智能(AI)领域的投资力度。此举紧随其近期一笔185亿美元巨额融资之后,凸显了软银在AI领域的战略布局。据悉,软银还…

    2026年8月28日
    100
  • 如何解决PHP中数字转换为文字的问题?使用kwn/number-to-words库可以轻松搞定!

    可以通过一下地址学习composer:学习地址 在开发一个多语言支持的财务系统时,我遇到了一个棘手的问题:需要将数字转换为相应语言的文字描述。这在处理金额时尤为重要,因为用户需要看到像“五千零九十九美元九十九美分”这样的描述,而不是单纯的数字。为了解决这个问题,我尝试了多种方法,最终找到了kwn/n…

    用户投稿 2026年8月28日
    100
  • CentOS7多网卡绑定指南

    CentOS7多网卡绑定指南CentOS7多网卡绑定指南CentOS7多网卡绑定指南CentOS7多网卡绑定指南

    在linux 7.0及以上系统中,网络服务由networkmanager集中管控。为实现高效的链路聚合,red hat引入了team工具用于多网卡绑定配置。本文将以主备模式为例,详细介绍如何利用team技术提升网络的稳定性与性能。相关操作方法在red hat官方推荐文档《linux就该这么学》中也有…

    2026年8月28日 用户投稿
    200
  • 将越狱问题转换为求解逻辑推理题:「滥用」推理能力让LLM实现自我越狱

    将越狱问题转换为求解逻辑推理题:「滥用」推理能力让LLM实现自我越狱将越狱问题转换为求解逻辑推理题:「滥用」推理能力让LLM实现自我越狱将越狱问题转换为求解逻辑推理题:「滥用」推理能力让LLM实现自我越狱将越狱问题转换为求解逻辑推理题:「滥用」推理能力让LLM实现自我越狱

    北京航空航天大学、360 ai 安全实验室、新加坡国立大学和南洋理工大学的研究团队联合发布了一项关于大型语言模型(llms)安全性的重要研究成果。该研究提出了一种名为“推理增强对话”(race)的新型多轮攻击框架,能够有效突破llms的安全对齐机制。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜…

    2026年8月28日 用户投稿
    100
  • 如何解决CampaignMonitorAPI集成问题?使用Composer和createsend-php库可以轻松实现!

    可以通过一下地址学习composer:学习地址 在开发一个电子邮件营销系统时,我遇到了一个棘手的问题:如何高效地集成campaign monitor api。虽然我知道campaign monitor提供了强大的api,但我不知道如何在php项目中无缝集成它。尝试了各种方法后,我终于找到了一个完美的…

    用户投稿 2026年8月28日
    000

发表回复

登录后才能评论
关注微信