0

0

c++如何实现单例模式_c++线程安全单例模式写法【面试】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-09 16:02:02

|

630人浏览过

|

来源于php中文网

原创

C++11 之前 double-checked locking 不安全,因编译器和 CPU 重排序可能导致 instance 指针提前赋值而对象未构造完成;C++11 起推荐用 static 局部变量实现单例,由编译器保证线程安全初始化。

c++如何实现单例模式_c++线程安全单例模式写法【面试】

为什么 double-checked locking 在 C++11 之前不安全

因为编译器重排序和 CPU 指令重排,可能导致 instance 指针被提前赋值,但对象构造尚未完成。线程 A 执行到 if (instance == nullptr) 时看到非空指针,就直接返回未初始化完毕的对象,引发未定义行为。

在 C++11 之前,必须用全局锁(如 pthread_mutex_t)包裹整个获取逻辑,性能差;C++11 引入内存模型后,才真正支持高效且安全的双重检查锁定。

C++11 推荐写法:使用 std::call_once + static 局部变量

这是最简洁、最安全、且天然线程安全的实现方式,由编译器保证初始化仅执行一次,无需手动加锁或检查。

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance; // C++11 起,static 局部变量初始化是线程安全的
        return instance;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private: Singleton() = default; // 可加初始化逻辑 };

  • 所有主流编译器(GCC、Clang、MSVC)都已正确实现该语义
  • 首次调用 getInstance() 时才构造对象,满足懒加载
  • 无需 std::mutexstd::atomic,无额外开销
  • 析构由程序退出前自动触发,顺序可控(静态对象生命周期)

如果非要手写 double-checked locking:必须用 std::atomicmemory_order

手动实现需严格控制内存序,否则仍可能出错。关键点不是“加锁”,而是防止重排破坏构造顺序。

PathFinder
PathFinder

AI驱动的销售漏斗分析工具

下载

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

class Singleton {
public:
    static Singleton* getInstance() {
        Singleton* tmp = instance.load(std::memory_order_acquire);
        if (tmp == nullptr) {
            std::lock_guard lock(mutex_);
            tmp = instance.load(std::memory_order_relaxed);
            if (tmp == nullptr) {
                tmp = new Singleton();
                instance.store(tmp, std::memory_order_release);
            }
        }
        return tmp;
    }

private: static std::atomic> instance; static std::mutex mutex_; Singleton() = default; }; std::atomic> Singleton::instance{nullptr}; std::mutex Singleton::mutex_;

  • instance 必须是 std::atomic,不能是裸指针
  • 第一次 load 用 memory_order_acquire,确保后续读取不会重排到它前面
  • store 用 memory_order_release,配合 acquire 实现同步点
  • 内部二次 check 是必须的:防止多个线程同时通过第一层 if 后竞争构造
  • 实际项目中几乎没必要这么写,static 局部变量更可靠

面试时最容易被追问的坑

面试官常会问:“如果 Singleton 构造函数抛异常,会怎样?”——答案是:static 局部变量版本会捕获异常,且下次调用仍会尝试构造(C++11 标准规定:若初始化抛异常,该变量视为未初始化,下次进入函数时重试)。

  • 这意味着构造函数必须能处理重复调用的副作用(比如文件打开失败、网络连接失败等)
  • 而手写 double-checked 版本若在 new Singleton() 后、store 前抛异常,会导致 instance 保持为 nullptr,下次调用可重试,行为一致
  • 但若在构造函数中发生资源泄漏(比如 malloc 成功但后续失败),静态局部变量版无法自动回滚,需自行确保构造函数强异常安全

真正难的不是写出来,而是说清“为什么这个 static 变量能线程安全”——本质是编译器生成了类似 std::call_once 的保护代码,背后依赖的是 C++11 的 one-time initialization 机制。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

800

2023.08.22

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

173

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

104

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

613

2023.08.10

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

22

2025.11.16

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

126

2026.02.06

java多线程方法汇总
java多线程方法汇总

本专题整合了java多线程面试题、实现函数、执行并发相关内容,阅读专题下面的文章了解更多详细内容。

49

2026.02.06

1688阿里巴巴货源平台入口与批发采购指南
1688阿里巴巴货源平台入口与批发采购指南

本专题整理了1688阿里巴巴批发进货平台的最新入口地址与在线采购指南,帮助用户快速找到官方网站入口,了解如何进行批发采购、货源选择以及厂家直销等功能,提升采购效率与平台使用体验。

682

2026.02.06

快手网页版入口与电脑端使用指南 快手官方短视频观看入口
快手网页版入口与电脑端使用指南 快手官方短视频观看入口

本专题汇总了快手网页版的最新入口地址和电脑版使用方法,详细提供快手官网直接访问链接、网页端操作教程,以及如何无需下载安装直接观看短视频的方式,帮助用户轻松浏览和观看快手短视频内容。

390

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9万人学习

C 教程
C 教程

共75课时 | 4.6万人学习

C++教程
C++教程

共115课时 | 16.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号