DoubleBuffer + shared_ptr 设计模式详解
一、背景:要解决什么问题?
在高并发服务中,经常会遇到这样的需求:
-
配置 / 策略 / 规则 需要动态更新
-
读请求 非常频繁
-
更新 相对较少
-
不能因为更新 阻塞或影响读请求
核心诉求:读要极快,最好无锁;写可以慢一点,但要安全。
1、最基础写法
std::string current_notice;
std::string getNotice() {
return current_notice;
}
void updateNotice(const std::string& n) {
current_notice = n;
}
问题:在多线程下:一个线程在读 current_notice,另一个线程正在改 current_notice,这就会造成
- 数据竞争
- 可能读到一半
- 未定义行为
2、加锁写法
std::mutex m;
std::string current_notice;
std::string getNotice() {
std::lock_guard<std::mutex> lk(m);
return current_notice;
}
void updateNotice(const std::string& n) {
std::lock_guard<std::mutex> lk(m);
current_notice = n;
}
问题:读请求非常多,每次都要抢锁,高并发下 性能下降明显。
二、DoubleBuffer 是什么?
DoubleBuffer(双缓冲) 的核心思想是:始终维护两份数据。
-
一份给读线程用(active)
-
一份给写线程改(inactive)
当写完后,将写线程数据切换给读线程。
但还有一个隐藏问题:谁负责撤掉读线程?
三、shared_ptr:自动“等所有读线程看完后再撤”
shared_ptr引用计数的方式可以确认当前是否有读操作。
没有读操作的时候引用计数清零自动析构,再次读的时候直接从写操作拷贝一份来读
未完待续。。。

浙公网安备 33010602011771号