c++中如何使用std::shared_lock实现读写锁_c++多线程性能优化【实例】

1次阅读

不能。std::shared_lock 只是配合 std::shared_mutex 或 std::shared_timed_mutex 使用的 RAII 共享锁包装器,自身不实现读写锁逻辑,仅负责构造时调用 lock_shared()、析构时释放,必须与支持共享语义的互斥体搭配使用。

c++ 中如何使用 std::shared_lock 实现读写锁_c++ 多线程性能优化【实例】

std::shared_lock 能不能单独实现读写锁?

不能。std::shared_lock 本身只是共享所有权的只读锁包装器,它不持 有锁,也不管理底层互斥体的加锁逻辑。真正实现读写语义的是它配合的 std::shared_mutex(C++17 引入)或 std::shared_timed_mutex(C++14)。std::shared_lock 只负责在构造时调用 lock_shared()、析构时自动释放共享锁——它本质是 RAII 封装,不是锁本身。

正确搭配 std::shared_mutex 使用 shared_lock 的写法

必须用 std::shared_mutex 作为底层同步原语,再分别用 std::shared_lock(读)和 std::unique_lock(写)来访问:

std::shared_mutex rw_mutex; std::vector data;  // 读操作:多个线程可并发 void read_data() {     std::shared_lock lock(rw_mutex); // 自动调用 lock_shared()     for (int x : data) {// 安全读取} }  // 写操作:排他,阻塞所有读 / 写 void write_data(int x) {std::unique_lock lock(rw_mutex); // 自动调用 lock()     data.push_back(x); }

注意:std::shared_lock 构造时默认行为是阻塞等待共享锁,不支持超时或尝试获取(除非显式传 std::defer_lock 后手动调用 try_lock_shared())。

常见误用与性能陷阱

  • 混用 std::mutexstd::shared_lock:编译直接报错,因为 std::shared_lock 要求模板参数支持 lock_shared(),而 std::mutex 没有该成员函数
  • 读操作用了 std::unique_lock<:shared_mutex>:虽能工作,但完全丧失并发读能力,退化为普通互斥锁
  • 在循环内反复构造 std::shared_lock:频繁加锁 / 解锁开销大;应把锁粒度控制在真正需要保护的 数据访问 范围内,而非每行都锁
  • Windows 上 VS2019 早期版本对 std::shared_mutex 实现有 bug(如 spurious wakeups),建议升级到 VS2019 16.8+ 或改用第三方实现(如 boost::shared_mutex)

什么时候不该用 shared_mutex?

当读操作极短(比如仅读一个 int)、或读写比极低(写远多于读)时,std::shared_mutex 的内部原子操作和队列管理反而比 std::mutex 更重。实测表明,在简单场景下,它的吞吐可能比普通互斥锁低 10%~30%。

立即学习C++ 免费学习笔记(深入)”;

真正受益的场景是:读操作耗时明显(如遍历容器、序列化结构体)、且读频次显著高于写频次(例如配置缓存、只读元数据表)。

text=ZqhQzanResources