C++ 并发专题 - 线程安全的单例模式
一:概述:
在C++编程中,call_once
是一种机制,用于确保某个函数或代码段在多线程环境下仅被调用一次。这种机制常用于初始化资源、配置全局变量或执行只需执行一次的逻辑。在 C++11 标准中,std::call_once
是由标准库提供的工具,它与 std::once_flag
配合使用,能够实现线程安全的一次性初始化。
二:工作原理:
std::once_flag
:是一个标志,标识某段代码是否已经被调用过。std::call_once
:接收一个std::once_flag
和一个函数/可调用对象,只在第一次调用时执行,后续调用直接返回
三:特点和优点
- 线程安全:即使多个线程同时调用,
std::call_once
也保证函数只执行一次。 - 性能优化:相比手写的双重检查锁机制,
std::call_once
更简洁、易用且高效。 - 无锁实现:在实现细节上,现代标准库可能会使用无锁算法,减少锁竞争的开销。
四:例子(线程安全的单例模式)
#include <iostream>
#include <mutex>
// 单例类 MySingleton
class MySingleton {
private:
static std::once_flag initInstanceFlag; // 标志位,确保初始化函数只调用一次
static MySingleton * instance; // 指向单例实例的静态指针
// 私有化构造函数和析构函数,防止外部创建或销毁实例
MySingleton() = default;
~MySingleton() = default;
public:
// 删除拷贝构造函数和赋值运算符,防止复制或赋值单例对象
MySingleton(const MySingleton&) = delete;
MySingleton& operator = (const MySingleton&) = delete;
// 获取单例实例的方法
static MySingleton * getInstance() {
// 使用 std::call_once 确保 initSingleton 只被调用一次
std::call_once(initInstanceFlag, MySingleton::initSingleton);
return instance;
}
// 初始化单例实例的静态方法
static void initSingleton() {
instance = new MySingleton();
}
};
// 定义静态成员变量,初始化为空
MySingleton * MySingleton::instance = nullptr;
std::once_flag MySingleton::initInstanceFlag;
int main() {
// 输出空行,仅用于美化输出
std::cout << '\n';
// 第一次调用 getInstance 时,初始化单例对象
std::cout << "MySingleton::getInstance(): " << MySingleton::getInstance() << '\n';
// 第二次调用 getInstance,不会重新初始化,返回同一个实例
std::cout << "MySingleton::getInstance(): " << MySingleton::getInstance() << '\n';
std::cout << '\n'; // 输出空行,美化输出
}