新闻中心

c++怎么实现一个线程安全的单例模式_c++线程安全单例模式的多种实现方式

2025-11-09
浏览次数:
返回列表
C++中线程安全单例模式有四种实现:1. 局部静态变量(C++11起线程安全),代码简洁、延迟初始化,推荐使用;2. 双重检查锁定,性能好但需手动管理内存;3. 智能指针+双重检查,安全且自动管理内存,但较复杂;4. 静态初始化(饿汉模式),线程安全但不支持延迟加载。优先推荐局部静态变量方式。

c++怎么实现一个线程安全的单例模式_c++线程安全单例模式的多种实现方式

在C++中实现线程安全的单例模式,关键在于确保多个线程同时调用单例的获取方法时,实例只被创建一次,并且不会出现竞态条件。以下是几种常见的线程安全单例实现方式,从简单到灵活,适用于不同场景。

1. 利用局部静态变量(C++11 起线程安全)

这是最简洁且推荐的方式,适用于大多数情况。

C++11 标准规定:函数内的局部静态变量的初始化是线程安全的,由编译器保证只有一个线程完成初始化。

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;  // 局部静态变量,C++11 线程安全
        return instance;
    }
<pre class='brush:php;toolbar:false;'>Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

private: Singleton() = default; ~Singleton() = default; };

优点:代码简洁,无需手动加锁,延迟初始化,自动析构。

注意:该方式依赖 C++11 及以上标准。

2. 双重检查锁定(Double-Checked Locking)

在手动管理线程同步时常用,避免每次调用都加锁。

#include <mutex>
<p>class Singleton {
public:
static Singleton* getInstance() {
if (instance == nullptr) {  // 第一次检查
std::lock<em>guard<std::mutex> lock(mutex</em>);
if (instance == nullptr) {  // 第二次检查
instance = new Singleton();
}
}
return instance;
}</p><pre class="brush:php;toolbar:false;">Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

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

<code>static Singleton* instance;
static std::mutex mutex_;

};

// 静态成员定义 Singleton* Singleton::instance = nullptr; std::mutex Singleton::mutex_;

优点:性能较好,仅在首次创建时加锁。

注意:必须使用指针和动态分配,需手动管理内存或配合智能指针;new 可能抛出异常,但此处影响较小。

3. 使用智能指针 + 双重检查(更安全)

结合 std::atomicstd::shared_ptr 提高安全性与自动内存管理。

BJXSHOP网上开店专家 BJXSHOP网上开店专家

BJXShop网上购物系统是一个高效、稳定、安全的电子商店销售平台,经过近三年市场的考验,在中国网购系统中属领先水平;完善的订单管理、销售统计系统;网站模版可DIY、亦可导入导出;会员、商品种类和价格均实现无限等级;管理员权限可细分;整合了多种在线支付接口;强有力搜索引擎支持... 程序更新:此版本是伴江行官方商业版程序,已经终止销售,现于免费给大家使用。比其以前的免费版功能增加了:1,整合了论坛

BJXSHOP网上开店专家 0 查看详情 BJXSHOP网上开店专家
#include <memory>
#include <mutex>
#include <atomic>
<p>class Singleton {
public:
static std::shared_ptr<Singleton> getInstance() {
std::shared_ptr<Singleton> tmp = instance.load();
if (tmp == nullptr) {
std::lock<em>guard<std::mutex> lock(mutex</em>);
tmp = instance.load();
if (tmp == nullptr) {
tmp = std::shared_ptr<Singleton>(new Singleton());
instance.store(tmp);
}
}
return tmp;
}</p><pre class='brush:php;toolbar:false;'>Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

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

static std::atomic<std::shared_ptr<Singleton>> instance;
static std::mutex mutex_;

};

// 静态成员定义 std::atomic<:shared>ptr> Singleton::instance{nullptr}; std::mutex Singleton::mutex;

优点:自动内存管理,避免内存泄漏;原子操作提升并发安全性。

缺点:相对复杂,性能略低于局部静态变量方式。

4. 程序启动时静态初始化(饿汉模式)

在程序启动时就创建实例,天然线程安全。

class Singleton {
public:
    static Singleton& getInstance() {
        return instance;
    }
<pre class='brush:php;toolbar:false;'>Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

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

<code>static Singleton instance;  // 静态成员,在 main 前构造

};

Singleton Singleton::instance; // 全局初始化

优点:绝对线程安全,无锁,调用快。

缺点:不支持延迟加载,即使未使用也会构造,可能浪费资源。

基本上就这些常见方式。推荐优先使用局部静态变量方式(C++11+),简洁高效又安全。若需更精细控制生命周期或兼容旧标准,可考虑双重检查或静态初始化。选择哪种方式,取决于项目需求、编译器支持和性能要求。

以上就是c++++怎么实现一个线程安全的单例模式_c++线程安全单例模式的多种实现方式的详细内容,更多请关注其它相关文章!


# 内存管理  # 智慧景区网站建设  # 轴承网站建设好处  # 推广企业网站收费  # 优化网站-搭建网站  # 怎样优化网站首页内容  # seo是什么意思关键词排名优  # 网站优化域名要求  # 临县信息化网站推广报价  # 生态恢复案例网站建设  # 普洱网络营销推广公司  # 也会  # 边缘  # ai  # 这是  # 是一个  # 适用于  # 加锁  # 加载  # 网上开店  # 游戏开发  # red  # 无锁  # 延迟加载  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: CSS自定义字体样式被系统字体替换怎么办_font-face方式指定font-display控制渲染策略  Win11怎么查看显卡显存 Win11显示适配器属性及专用视频内存查询  必由学网页版入口 必由学官方平台直接访问  顺丰快递查询系统 官方正版查询入口  漫蛙2在线漫画入口 漫蛙正版漫画网页版直达  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  UC浏览器网页版登录入口官网 电脑版网址入口  Word2013如何插入视频和音频媒体_Word2013媒体插入的多媒体支持  mcjs网页版流畅运行 mcjs低配电脑畅玩入口  Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖  Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践  极速漫画官方主页网址 极速漫画漫画在线浏览官网链接  PySpark中从现有列右侧提取可变长度字符创建新列的教程  ArrayList与LinkedList核心操作的Big-O复杂度分析  J*a TimerTask中HashMap意外清空的深层原因与解决方案  韩剧圈正版入口页面_韩剧圈官网登录链接  PHP中高效并行检查多链接状态的教程  我的世界官方游戏入口 我的世界官网平台直达链接  Win10磁盘清理工具在哪 Win10打开并使用磁盘清理【教程】  学习通网页版官方登录 超星学习通电脑端入口指南  Golang如何使用new_Go new分配内存机制讲解  Spyder启动失败:字体文件权限拒绝错误解决方案  cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法  J*a如何使用AtomicInteger控制计数_J*a无锁计数器性能分析  特斯拉自动驾驶房车计划曝光 原型车将于2027年亮相  J*aScript:在map操作中高效处理空数组  MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏  深入理解Go语言中的指针类型:以*string为例  Win10如何清理注册表垃圾 Win10注册表维护与优化指南【慎用】  CSS如何设置hover状态颜色_hover伪类调整背景或文字颜色  如何创建没有密码的Windows本地账户_跳过微软账户登录的技巧【教程】  顺丰国际快递查询 国际件官方查询入口  Go语言中对Map值调用带指针接收者方法:原理与最佳实践  解决 Vaadin 8 中大文件音频播放与定位时出现的 IOException  Go语言HTML解析:利用Goquery精准获取指定元素内容  2026年CSGO开箱网站推荐 CSGO开箱平台精选  Golang如何实现Web接口签名验证_Golang Web接口签名校验开发方法  win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】  修复二维数组索引越界异常:一维循环到二维坐标的正确映射  Go语言中的*string:深入理解字符串指针  葱吃多了会怎样 葱吃多了会伤胃吗  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  Win11怎么关闭快速启动_Win11彻底关机设置教程  C++如何比较两个字符串_C++ string compare函数与操作符对比  Steam官网入口直达 Steam注册及登录步骤  解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  mc.js官网登录入口 mc.js官方登录入口最新版  天眼查怎么看公司融资情况 天眼查企业融资历史查询步骤【攻略】 

搜索