如何创建线程安全的OwnerRef引用包装器?
实现带自动锁机制的OwnerRef引用包装器
问题背景
现有Mutexed模板类的设计存在线程安全缺陷:Acquire()方法中使用std::lock_guard仅在函数返回前持有互斥锁,返回裸指针T*后,后续对对象的访问不再受锁保护,无法保证多线程环境下的操作安全。我们需要实现一个OwnerRef引用包装器,让它在自身生命周期内持续持有锁,析构时自动释放,确保从获取引用到引用销毁的整个过程中,目标对象始终处于被保护状态。
原代码如下:
template <typename T, class Mutex = twist::ed::stdlike::mutex> class Mutexed { // 待实现的自定义OwnerRef using OwnerRef = T*; public: template <typename... Args> explicit Mutexed(Args&&... args) : object_(std::forward<Args>(args)...) { } OwnerRef Acquire() { std::lock_guard guard(mutex_); return &object_; } private: T object_; Mutex mutex_; // 保护object_的互斥锁 }; ////////////////////////////////////////////////////////////////////// template <typename T> auto Acquire(Mutexed<T>& object) { return object.Acquire(); }
期望的安全使用方式:
Mutexed<std::vector<Apple>> apples; { auto owner_ref = apples.Acquire(); // 此处自动获取锁 owner_ref->push_back(Apple{}); // 对象访问全程受锁保护 } // owner_ref析构,自动释放锁
解决方案实现
你尝试的OwnerRef类思路完全正确,只需稍作调整完善,即可满足需求:
template <typename T, class Mutex = twist::ed::stdlike::mutex> class Mutexed { // 将OwnerRef定义为内部类,紧密关联Mutexed的锁和对象 class OwnerRef { public: // 构造时绑定对象指针并获取锁 OwnerRef(T* obj, Mutex& mutex) : m_obj(obj), guard(mutex) { // std::lock_guard构造时自动加锁 } // 重载->运算符,模拟指针访问语法 T* operator->() { return m_obj; } // 可选:重载*运算符,支持直接解引用 T& operator*() { return *m_obj; } private: T* m_obj; std::lock_guard<Mutex> guard; // 持有锁,析构时自动释放 }; public: template <typename... Args> explicit Mutexed(Args&&... args) : object_(std::forward<Args>(args)...) { } // 返回OwnerRef对象,而非裸指针 OwnerRef Acquire() { return OwnerRef(&object_, mutex_); } private: T object_; Mutex mutex_; }; ////////////////////////////////////////////////////////////////////// template <typename T> auto Acquire(Mutexed<T>& object) { return object.Acquire(); }
关键设计说明
OwnerRef作为Mutexed的内部类,结构上更紧凑,能直接关联到所属的互斥锁和对象- 利用RAII特性:
std::lock_guard在OwnerRef构造时自动加锁,在OwnerRef析构时自动解锁,无需手动管理锁的生命周期 - 重载
operator->和operator*,让OwnerRef的使用方式和裸指针/原生引用完全一致,降低学习和使用成本 - 只要
OwnerRef对象存在,互斥锁就会持续持有,所有通过OwnerRef对object_的操作都会受到锁的保护,彻底解决原代码的线程安全问题
内容的提问来源于stack exchange,提问作者indigo153
相关产品推荐
相关产品推荐

