如何面向未来兼容C++ std::shared_ptr、std::unique_ptr的线程安全并发访问
C++智能指针并发访问跨版本兼容实现方案
核心设计思路
- 基于标准内置的
__cplusplus宏自动检测C++版本,切换底层实现逻辑,无需手动修改编译配置 - 宏封装层与业务代码完全解耦,后续C++20原子智能指针特性普及后,仅需修改宏定义即可完成升级,业务逻辑无需调整
- 严格遵循前提结论设计,不引入额外不必要的同步开销,兼顾性能与安全性
跨版本适配宏定义
#include <atomic> #include <memory> #include <mutex> // 自动识别C++版本,切换实现 #if __cplusplus >= 202002L /************************************* C++20及以上版本实现 *************************************/ // 基础原子操作封装,当前兼容C++17风格调用,后续可直接切换为原生atomic<shared_ptr>实现 #define SHARED_GET(public_shared) std::atomic_load(&public_shared) #define SHARED_SET(public_shared, new_val) std::atomic_store(&public_shared, new_val) #define UNIQUE_GET(public_unique) std::atomic_load(&public_unique) #define UNIQUE_SET(public_unique, new_val) std::atomic_store(&public_unique, new_val) /* 待编译器对std::atomic<std::shared_ptr>支持普及后,可替换为以下原生无锁实现,业务代码无需修改 #define SHARED_GET(atomic_public_shared) atomic_public_shared.load() #define SHARED_SET(atomic_public_shared, new_val) atomic_public_shared.store(new_val) #define UNIQUE_GET(atomic_public_unique) atomic_public_unique.load() #define UNIQUE_SET(atomic_public_unique, new_val) atomic_public_unique.store(new_val) */ #else /************************************* C++17及更早版本实现 *************************************/ #define SHARED_GET(public_shared) std::atomic_load(&public_shared) #define SHARED_SET(public_shared, new_val) std::atomic_store(&public_shared, new_val) #define UNIQUE_GET(public_unique) std::atomic_load(&public_unique) #define UNIQUE_SET(public_unique, new_val) std::atomic_store(&public_unique, new_val) #endif /************************************* 通用业务层宏定义 *************************************/ // 从公共共享的shared_ptr实例创建本地无竞争副本 #define MAKE_LOCAL_SHARED(local_name, public_shared) auto local_name = SHARED_GET(public_shared) // shared_ptr指向对象访问保护,需传入绑定到对应对象的互斥量 #define BEGIN_USE_SHARED_TGT(local_shared, mutex_obj) \ do { \ std::lock_guard<std::mutex> guard(mutex_obj); #define END_USE_SHARED_TGT } while(0) // unique_ptr指向对象访问保护,队列保证独占场景下无锁,仅做语义标记 #define BEGIN_USE_UNIQUE_TGT(local_unique) #define END_USE_UNIQUE_TGT
使用示例
// 公共资源定义 std::shared_ptr<MyBusinessClass> g_shared_biz_obj; std::unique_ptr<MyBusinessClass> g_unique_biz_obj; std::mutex g_shared_biz_mutex; // 与g_shared_biz_obj指向的对象绑定 // 业务线程逻辑 void worker_thread() { // 1. 生成shared_ptr本地副本,无并发竞争 MAKE_LOCAL_SHARED(local_shared, g_shared_biz_obj); // 2. 安全访问shared_ptr指向的对象 BEGIN_USE_SHARED_TGT(local_shared, g_shared_biz_mutex) local_shared->process_data(); local_shared->update_status(); END_USE_SHARED_TGT; // 3. 接收队列传递的unique_ptr独占实例 auto local_unique = std::move(g_unique_biz_obj); // 无需加锁直接访问,仅做语义标记 BEGIN_USE_UNIQUE_TGT(local_unique) local_unique->single_thread_process(); END_USE_UNIQUE_TGT; }
注意事项
- 所有公共全局/跨线程传递的智能指针实例,必须仅通过上述
SHARED_GET/SHARED_SET/UNIQUE_GET/UNIQUE_SET宏访问,禁止直接读写操作 unique_ptr的无锁访问依赖队列的独占保证,必须确保同一时间只有一个线程持有该unique_ptr实例- 保护指向对象的互斥量需要与对应智能指针指向的对象绑定管理,避免出现用错互斥量导致的并发问题
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

