【中间件】brpc_基础_单例
文章目录
- brpc 单例
- 1 实现核心机制
- 2 代码结构解析
- 3 关键设计点
- 4 使用示例
- 5 潜在改进与限制
- 6 与标准单例实现的对比
- 7 总结
brpc 单例
源码
1 实现核心机制
-
基于
bthread_once
的线程安全初始化
通过 BRPC 的bthread_once
函数确保单例的初始化在多线程(bthread 环境)中仅执行一次。bthread_once
的作用类似于pthread_once
,但专为 BRPC 的用户态线程(bthread)设计,确保初始化函数在所有 bthread 中仅被调用一次。 -
模板化设计
使用模板类SingletonOnBthreadOnce
,允许用户将任意类封装为单例。用户只需通过SingletonOnBthreadOnce<T>::get_instance()
即可获取单例实例,无需重复编写单例逻辑。
2 代码结构解析
// 模板类定义
template <typename T>
class SingletonOnBthreadOnce {
public:// 获取单例实例的入口方法static T* get_instance() {bthread_once(&once_control, init); // 确保 init 仅执行一次return instance;}private:// 初始化函数:创建单例对象static void init() {instance = new T();}// 静态成员:控制一次性初始化的标志static bthread_once_t once_control;// 静态成员:单例实例指针static T* instance;
};// 模板静态成员初始化(关键!)
template <typename T>
bthread_once_t SingletonOnBthreadOnce<T>::once_control = BTHREAD_ONCE_INIT;template <typename T>
T* SingletonOnBthreadOnce<T>::instance = nullptr;
3 关键设计点
-
线程安全性
通过bthread_once
保证init()
函数在所有 bthread 中仅执行一次,避免多线程竞争导致的多次实例化。 -
延迟初始化(Lazy Initialization)
单例实例在首次调用get_instance()
时创建,避免程序启动时的全局初始化开销。 -
内存管理
单例对象通过new
创建,但未提供销毁接口,依赖进程退出时操作系统自动回收内存。这种设计简化了实现,但可能导致资源泄漏(如文件句柄未释放)。 -
模板静态成员定义
静态成员once_control
和instance
在模板类外部分别初始化为BTHREAD_ONCE_INIT
和nullptr
,确保链接时正确生成符号。
4 使用示例
// 用户自定义类(需可访问构造函数)
class MyConfig {
public:MyConfig() { /* 初始化逻辑 */ }void load(const std::string& path) { /* ... */ }
};// 获取单例实例
MyConfig* config = SingletonOnBthreadOnce<MyConfig>::get_instance();
config->load("path/to/config");
5 潜在改进与限制
-
构造函数访问权限
要求用户类的构造函数为公有或对SingletonOnBthreadOnce
开放友元。若需严格封装,用户需手动添加友元声明:class MyConfig { private:MyConfig() = default;friend class SingletonOnBthreadOnce<MyConfig>; };
-
销毁机制缺失
未提供delete_instance()
方法,若需主动释放资源,可扩展模板类:static void destroy() {delete instance;instance = nullptr;once_control = BTHREAD_ONCE_INIT; // 重置以便重新初始化(需谨慎) }
-
异常处理
若T
的构造函数抛出异常,bthread_once
会标记初始化未完成,下次调用get_instance()
时将重试初始化。需确保构造函数幂等性或处理异常场景。
6 与标准单例实现的对比
特性 | BRPC 单例 | Meyer’s Singleton(C++11) |
---|---|---|
线程安全 | 依赖 bthread_once ,适用于 bthread 环境 | 依赖静态局部变量初始化,原生线程安全 |
初始化时机 | 延迟初始化 | 延迟初始化 |
内存管理 | 显式 new ,依赖进程退出回收 | 静态对象,自动析构(可能受析构顺序影响) |
适用场景 | BRPC/bthread 项目 | 通用 C++ 项目 |
代码复杂度 | 需模板和静态成员定义 | 极简(static T& instance() { static T obj; return obj; } ) |
7 总结
singleton_on_bthread_once.h
提供了一种基于 BRPC 用户态线程(bthread)的单例模式实现,核心优势在于:
- 线程安全初始化:通过
bthread_once
确保跨 bthread 的唯一性。 - 低侵入性:用户类无需修改即可封装为单例。
- 延迟加载:减少启动开销。
其局限性主要在于:
- 依赖 BRPC 环境:不适用于非 BRPC 项目。
- 内存泄漏风险:无显式销毁接口。
- 构造函数权限要求:需用户类构造函数可访问。
适合在 BRPC 高并发服务中管理全局配置、资源池等需线程安全访问的单例对象。