std::shared_mutex是C++17标准库提供的读写锁,支持多读单写;应使用std::shared_lock管理读锁、std::unique_lock管理写锁,禁用std::lock_guard;其性能受平台实现影响,适用于读多写少且读操作轻量的场景。

std::shared_mutex 是 C++17 引入的,不是自己实现的
它由标准库提供,底层依赖操作系统原语(如 pthread_rwlock_t 或 Windows SRWLock),你不能也不该手动“实现”一个符合标准行为的 std::shared_mutex。想用读写锁,直接用标准库即可;想理解原理,得看 libc++/libstdc++ 源码或系统 API 封装逻辑。
怎么正确使用 std::shared_mutex 的读写加锁
关键在区分读锁和写锁的 RAII 类型:用 std::shared_lock 获取共享(读)锁,用 std::unique_lock 获取独占(写)锁。混用或误用会导致编译失败或死锁。
-
std::shared_lock<:shared_mutex></:shared_mutex>:允许多个线程同时进入,但阻塞任何写操作 -
std::unique_lock<:shared_mutex></:shared_mutex>:排他性,会阻塞所有其他读/写锁获取 - 不能用
std::lock_guard—— 它不支持共享语义,编译报错:no matching function for call to 'lock_guard' - 写操作前必须确保没有活跃的
std::shared_lock,否则std::unique_lock会阻塞直到全部释放
示例:
std::shared_mutex rwmtx;
std::vector<int> data;
void read_data() {
std::shared_lock<std::shared_mutex> lock(rwmtx); // ✅ 正确
// ... 读 data
}
void write_data(int x) {
std::unique_lock<std::shared_mutex> lock(rwmtx); // ✅ 正确
data.push_back(x);
}
为什么 std::shared_mutex 在某些平台性能不如预期
Linux 上 libstdc++(GCC)默认用 pthread_rwlock_t,但 glibc 的实现存在 writer-starvation 问题:持续有读请求时,写锁可能无限期等待。Clang + libc++ 在 macOS 上用 os_unfair_lock + 自旋+睡眠混合策略,表现更均衡。
立即学习“C++免费学习笔记(深入)”;
- 高读低写场景下基本无感;但读写频繁交替时,
std::shared_mutex可能比简单std::mutex更慢 - 调试时注意:GDB 不识别
std::shared_mutex内部状态,无法像普通 mutex 那样查看是否被持有 - Windows 上 MSVC 使用 SRWLock,轻量且无 writer-starvation,但不支持递归锁或超时等待(
try_lock_for等)
替代方案:什么时候不该用 std::shared_mutex
它只适合“读多写少 + 读操作本身很快”的场景。如果读操作耗时长、或写操作频繁、或需要条件变量配合,它反而增加复杂度和风险。
- 读操作含 I/O、内存拷贝、或调用外部函数?→ 优先考虑复制数据 +
std::mutex,避免长时间持锁 - 需要唤醒等待写入的线程?→
std::shared_mutex不提供notify_one,得额外配std::condition_variable和普通 mutex - 要支持超时、中断取消、或跨线程迁移锁?→ 它不支持
std::try_to_lock以外的高级特性,std::shared_mutex的try_lock_for是 C++17 后才加入,且各实现兼容性不一
真正容易被忽略的是:std::shared_mutex 的构造/析构是平凡的,但它内部资源(如 pthread_rwlock_t)在首次加锁时才初始化 —— 所以首个 lock() 调用可能触发隐式分配,不宜放在 tight loop 里反复构造销毁。


















