std::shared_mutex是c++17读写锁,依赖os原生支持(pthread_rwlock_t或srwlock),需启用_cxx17且平台满足要求;必须配合shared_lock(读)或unique_lock(写)使用,不支持lock_guard;存在写饥饿、无写优先策略、跨平台兼容性差等问题,仅在读多写少且临界区长时具优势。

std::shared_mutex 是 C++17 引入的读写锁,但不能直接用于 Windows XP 或旧 MSVC 工具集
它在 Linux(glibc ≥ 2.26)和较新 Windows(Visual Studio 2015 Update 3 起,需 _HAS_CXX17 启用)上可用,但底层依赖 OS 原生支持:pthread_rwlock_t(Linux)或 SRWLOCK(Windows Vista+)。若目标平台不满足,编译会失败或退化为互斥模拟——此时性能反而更差。
- 检查是否启用 C++17:MSVC 需定义
_HAS_CXX17=1,Clang/GCC 需-std=c++17 - Windows 上若链接到旧 CRT(如 /MDd 对应 debug 版旧库),
std::shared_mutex构造可能抛出std::system_error,错误码为not_supported - 不要假设它“一定比
std::mutex快”——读多写少且临界区长时才体现优势;写操作仍会阻塞所有读,且内部有额外原子开销
正确使用 shared_lock 和 unique_lock 配合 shared_mutex
std::shared_mutex 本身不提供 lock/unlock 接口,必须搭配 std::shared_lock(共享)或 std::unique_lock(独占)使用。混用或漏写会导致未定义行为,比如用 std::lock_guard 包裹 std::shared_mutex 会编译失败。
- 读操作:用
std::shared_lock<:shared_mutex></:shared_mutex>,支持延迟构造、可移动、可try_lock_for - 写操作:只能用
std::unique_lock<:shared_mutex></:shared_mutex>,std::lock_guard不支持(无lock()成员) - 禁止跨作用域传递锁对象:
shared_lock移动后原对象变为未持有状态,再次 unlock 会抛异常
std::shared_mutex rwmtx;
std::vector<int> data;
<p>// 读
void read() {
std::shared_lock<std::shared_mutex> lock(rwmtx); // 自动 RAII
for (int x : data) { /<em> ... </em>/ }
}</p><p>// 写
void write(int x) {
std::unique_lock<std::shared_mutex> lock(rwmtx);
data.push_back(x);
}shared_mutex 的饥饿问题与写优先策略缺失
std::shared_mutex 标准未规定调度策略,实际实现多为“读优先”,即持续有读请求时,写线程可能无限等待(写饥饿)。它也不提供类似 std::shared_timed_mutex 的 try_lock_shared_for 之外的超时写锁接口,无法主动破除饥饿。
- 无法通过标准接口设置写优先;若业务要求强一致性(如配置热更新),需自行加计数器或信号量控制写请求准入
- 避免在循环中反复获取
shared_lock,尤其配合 long-running 读操作——这会显著延长写等待时间 - 调试时注意:GDB/Lldb 可能无法准确显示
shared_mutex当前持有者数量,需靠日志或自定义 wrapper 统计
替代方案:何时该放弃 shared_mutex 改用其他同步机制
当出现频繁写、数据结构简单、或需跨平台兼容旧系统时,std::shared_mutex 往往不是最优解。它的优势只在明确的“高并发读 + 低频写 + 大临界区”场景下成立。
立即学习“C++免费学习笔记(深入)”;
- 写占比 > 15%:直接用
std::mutex更轻量,避免共享锁的原子计数开销 - 需要乐观读(如 RCU 风格):考虑
std::atomic<t></t>+ hazard pointer,或absl::ReaderMutex(如果允许引入第三方) - 需细粒度控制(如分段锁):用
std::array<:shared_mutex n></:shared_mutex>分片保护容器,比单个锁扩展性更好
真正难的从来不是选对锁类型,而是识别出“这里其实根本不需要锁”——比如用无锁队列、copy-on-write vector 或只读快照,往往比调优 shared_mutex 更有效。











