【现代C++】mudou库中线程安全的Singleton单例类实现

127 阅读1分钟
#include <pthread.h>               // 提供pthread_once函数
#include <boost/noncopyable.hpp>  // 禁止拷贝构造和赋值操作

template<typename T>
class Singleton : boost::noncopyable  // 继承禁止拷贝的基类
{
public:
    static T& instance() {
        // 关键:pthread_once保证init函数仅执行一次(线程安全)
        pthread_once(&ponce_, &Singleton::init);
        return *value_;
    }

private:
    Singleton();          // 构造函数私有化
    ~Singleton();         // 析构函数私有化

    static void init() {  // 实际初始化函数
        value_ = new T(); // 创建单例对象
    }

private:
    // C++17, 允许静态成员变量使用inline直接定义+初始化
    inline static pthread_once_t ponce_ = PTHREAD_ONCE_INIT;  // once控制变量(线程安全初始化)
    inline static T* value_ = NULL;              // 单例对象指针
    
};

// Use example:
Foo& foo = Singleton<Foo>::instance();

该单例模式的线程安全由Pthreads库保证,使用pthread_once_t这个控制变量来保证lazy_initialization的线程安全。

使用静态的pthread_once_t类型控制变量,并初始化为PTHREAD_ONCE_INIT,该控制变量状态分为NEVER(未初始化)、IN_PROGRESS(初始化中)、DONE(已完成)。首次调用时,状态从NEVER转为IN_PROGRESS,初始化完成后标记为DONE

若多个线程同时调用pthread_once,只有第一个线程进入初始化流程,其他线程阻塞等待;初始化完成后,所有线程直接获取结果,保证了线程安全地初始化。避免了传统懒汉式单例需手动加锁(如pthread_mutex_lock)引入的性能开销。