C++如何实现单例模式的线程安全_C++双重检查锁定实现方法【架构】-C++

为什么直接用静态局部变量最安全

在 C++11 及以后,static 局部变量的初始化天然线程安全——编译器自动生成带 pthread_once 或类似机制的保护逻辑,无需手动加锁。这是目前最简洁、最可靠的方式,且无内存泄漏和指令重排风险。

常见错误是还在手写 getInstance() + std::mutex,既冗余又容易漏锁或死锁。更糟的是,有人用老式 double-checked locking(DCL)但没加 std::atomic 和内存序,导致在优化级别升高后崩溃。

  • 必须确保编译器支持 C++11 或更高标准(-std=c++11)
  • 不要在构造函数里调用其他单例的 getInstance(),否则可能引发静态初始化顺序问题
  • 若需延迟初始化且构造开销极大,静态局部变量仍适用;它只在第一次调用时构造,之后直接返回引用
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; // 可含复杂初始化逻辑 };

双重检查锁定(DCL)为何必须用 std::atomic 和 memory_order_acquire/release

原始 DCL(如 Java 风格)在 C++ 中不安全:编译器重排和 CPU 乱序可能导致 instance 指针被提前写入,而对象实际未构造完成。仅靠 std::mutex 锁两次是低效且错误的——第一次检查必须原子读,第二次写必须原子写+禁止重排。

关键点不是“加锁”,而是“控制可见性与执行顺序”。裸指针 + volatile 完全无效,volatile 不提供线程同步语义。

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

  • instance 必须声明为 std::atomic,不能是 Singleton*
  • 首次读用 load(std::memory_order_acquire),避免后续读被重排到其前
  • 写入用 store(ptr, std::memory_order_release),确保构造完成后再更新指针
  • 中间的 new Singleton 必须在锁内完成,且不能被编译器移到锁外
class Singleton {
public:
    static Singleton* getInstance() {
        Singleton* ptr = instance.load(std::memory_order_acquire);
        if (ptr == nullptr) {
            std::lock_guard lock(mutex_);
            ptr = instance.load(std::memory_order_acquire);
            if (ptr == nullptr) {
                ptr = new Singleton();
                instance.store(ptr, std::memory_order_release);
            }
        }
        return ptr;
    }

private: static std::atomic instance; static std::mutex mutex_; };

什么时候不该用单例,哪怕它线程安全

单例本质是全局状态,会隐式增加模块耦合、阻碍单元测试(无法 mock)、掩盖生命周期依赖。很多所谓“需要全局唯一”的场景,其实更适合依赖注入或作用域明确的工厂函数。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » C++如何实现单例模式的线程安全_C++双重检查锁定实现方法【架构】-C++
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4032149+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4032149+
  • 本周更新: 0+
  • 最后更新: 2026-03-16