手撕单例模式中的饿汉模式和懒汉模式,懒汉模式还要再多加一个C++11版本的
以下展示 C 中单例模式的三种常见实现饿汉模式、传统线程安全的懒汉模式双重检查锁定 以及 C11 版本的懒汉模式使用 Magic Static。#includeiostream#includemutex// ----------------------------- 1. 饿汉模式 -----------------------------// 在程序启动时即完成实例创建天然线程安全。// 缺点无论是否使用都会占用资源。classSingletonHungry{public:staticSingletonHungry*getInstance(){returninstance;}// 禁止拷贝和赋值SingletonHungry(constSingletonHungry)delete;SingletonHungryoperator(constSingletonHungry)delete;private:SingletonHungry(){std::coutHungry Singleton created.std::endl;}staticSingletonHungry instance;// 静态实例全局初始化};// 静态成员变量定义程序启动时初始化SingletonHungry SingletonHungry::instance;// ----------------------------- 2. 传统懒汉模式双重检查锁定 -----------------------------// 第一次使用时才创建实例通过互斥锁保证线程安全。// 注意由于内存可见性问题双重检查锁在早期 C 中可能失效需配合原子操作。// 这里使用 std::mutex 和双重检查作为示例。classSingletonLazy{public:staticSingletonLazy*getInstance(){if(instancenullptr){// 第一次检查std::lock_guardstd::mutexlock(mtx);if(instancenullptr){// 第二次检查instancenewSingletonLazy();}}returninstance;}SingletonLazy(constSingletonLazy)delete;SingletonLazyoperator(constSingletonLazy)delete;private:SingletonLazy(){std::coutLazy Singleton (traditional) created.std::endl;}staticSingletonLazy*instance;staticstd::mutex mtx;};SingletonLazy*SingletonLazy::instancenullptr;std::mutex SingletonLazy::mtx;// ----------------------------- 3. C11 懒汉模式Magic Static -----------------------------// 利用 C11 标准保证函数内静态局部变量的初始化是线程安全的。// 代码最简洁性能最优推荐使用。classSingletonCpp11{public:staticSingletonCpp11getInstance(){staticSingletonCpp11 instance;// 首次调用时初始化C11 保证线程安全returninstance;}SingletonCpp11(constSingletonCpp11)delete;SingletonCpp11operator(constSingletonCpp11)delete;private:SingletonCpp11(){std::coutLazy Singleton (C11) created.std::endl;}};// ----------------------------- 测试代码 -----------------------------intmain(){std::cout 饿汉模式 std::endl;auto*hungry1SingletonHungry::getInstance();auto*hungry2SingletonHungry::getInstance();std::cout地址相同: (hungry1hungry2)std::endl;std::cout\n 传统懒汉模式 std::endl;auto*lazy1SingletonLazy::getInstance();auto*lazy2SingletonLazy::getInstance();std::cout地址相同: (lazy1lazy2)std::endl;std::cout\n C11 懒汉模式 std::endl;autocpp111SingletonCpp11::getInstance();autocpp112SingletonCpp11::getInstance();std::cout地址相同: (cpp111cpp112)std::endl;return0;}关键说明注意C11 标准规定如果多个线程同时访问同一个函数内的静态局部变量初始化过程是线程安全的且只会执行一次。因此 static SingletonCpp11 instance; 是最推荐的现代 C 单例写法。