使用std::shared_ptr管理std::mutex生命周期及加解锁,是否为良好实践?
问题分析与解答
你的顾虑完全合理,这个实践不仅不符合C++标准库的设计语义,还存在严重的潜在问题,具体分析如下:
1. 核心功能逻辑错误:直接触发死锁
看你的main函数代码:
Lock lockA(&mtx); Lock lockB(lockA); Lock lockC(lockB);
当lockA构造时,会调用psmtx->lock()对全局mtx加锁;而lockB拷贝lockA时,会执行自身构造函数再次调用psmtx->lock()——但std::mutex是非递归互斥量,同一个线程对它重复加锁会直接触发死锁,程序会卡在lockB的构造步骤无法继续。
2. std::shared_ptr的误用:语义与场景完全不匹配
std::shared_ptr的设计初衷是管理动态分配对象的生命周期,实现共享所有权的自动释放。而你的场景中:
mtx是全局分配的对象,生命周期远长于所有Lock实例,根本不需要shared_ptr来管理它的生命周期- 你用
shared_ptr的自定义删除器执行unlock操作,完全扭曲了它的核心语义,会让其他开发者产生误解,大幅提升代码维护成本
3. RAII锁的语义偏离常规
标准库的std::lock_guard/std::unique_lock遵循一个锁对象对应一次加解锁的RAII语义:对象构造时加锁,析构时解锁,作用域结束自动释放锁,逻辑清晰且符合直觉。
而你的Lock类:
- 多个
Lock实例共享同一个shared_ptr,只有最后一个实例销毁时才会触发unlock - 每个新构造的
Lock实例都会重复加锁,完全违背了常规锁的使用逻辑,极易引发线程同步错误
合理的替代方案
如果你需要实现可拷贝的共享锁语义,应该使用标准库的std::shared_lock配合std::shared_mutex:
#include <shared_mutex> std::shared_mutex mtx; // 读取操作使用共享锁 void read_data() { std::shared_lock<std::shared_mutex> lock(mtx); // 安全读取数据 } // 写入操作使用独占锁 void write_data() { std::unique_lock<std::shared_mutex> lock(mtx); // 安全写入数据 }
如果只是需要常规的独占锁,直接用std::lock_guard或std::unique_lock即可,完全不需要自定义Lock类。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

