C++ 原子变量与引用计数类的派生类实现解析
核心结论
在C++中,原子变量(std::atomic)是实现线程安全引用计数类(如shared_ptr)的关键技术。原子变量通过原子操作(如CAS循环)确保引用计数的修改是不可分割的,从而避免多线程环境下的数据竞争问题。以下是核心实现要点:
原子变量的使用
- 类型定义:
std::atomic<std::size_t>用于存储引用计数,确保计数操作的原子性。 - 内存序控制:使用
std::memory_order_acq_rel确保计数操作的可见性和顺序性。
- 类型定义:
引用计数类的派生实现
- 控制块设计:独立的控制块(包含强引用计数和弱引用计数)管理对象生命周期。
- 关键操作:
- 构造函数:初始化计数器为1,关联对象。
- 析构函数:释放资源(计数归零时删除对象)。
- 拷贝/移动操作:通过原子操作更新计数器。
线程安全机制
- 原子操作:
fetch_sub和fetch_add实现线程安全的计数修改。 - 内存模型:
std::memory_order_acq_rel确保操作的顺序性和可见性。
- 原子操作:
实现示例
cppCopy Code
template<typename T> class SafeRefCount { private: T* ptr; std::atomic<std::size_t>* ref_count; void release() { if (ref_count && ref_count->fetch_sub(1, std::memory_order_acq_rel) == 1) { delete ptr; delete ref_count; } } public: SafeRefCount(T* p) : ptr(p), ref_count(new std::atomic<std::size_t>(1)) {} ~SafeRefCount() { release(); } SafeRefCount(const SafeRefCount& other) : ptr(other.ptr), ref_count(other.ref_count) { if (ref_count) ref_count->fetch_add(1, std::memory_order_relaxed); } SafeRefCount& operator=(const SafeRefCount& other) { if (this != &other) { release(); ptr = other.ptr; ref_count = other.ref_count; if (ref_count) ref_count->fetch_add(1, std::memory_order_relaxed); } return *this; } };
关键注意事项
性能优化:原子操作可能引入开销,需权衡线程安全与性能。
内存模型:
std::memory_order_acq_rel提供强同步,但可能影响吞吐量。
建议在实际项目中,优先使用std::shared_ptr,其内部实现经过高度优化。若需自定义,务必严格遵循原子操作规范,避免竞态条件。