std::shared_lock本质是读锁,需配对std::shared_mutex使用,读操作须为const且不修改数据,禁止锁升级,C++17起支持且需显式启用标准。

std::shared_lock 本质是读锁,不是万能的“并发读加速器”
它本身不提升读性能,只是允许多个线程**安全地同时读取同一资源**,前提是该资源的写操作被 std::shared_mutex 的独占锁(std::unique_lock)保护。如果你没配对使用 std::shared_mutex,或读操作里偷偷改了数据,std::shared_lock 就形同虚设。
常见错误现象:std::shared_lock 构造成功但程序崩溃 / 数据竞争 / ASan 报 data race on variable xxx —— 很可能是因为:你用了 std::shared_lock,但底层用的是普通 std::mutex,或者读逻辑里调用了非 const 成员函数修改了状态。
- 必须搭配
std::shared_mutex(C++17 起),不能用于std::mutex或std::recursive_mutex - 读操作函数应标记为
const,且内部不调用任何可能修改共享状态的函数 - 不要在
std::shared_lock持有期间调用未知实现的第三方函数——它可能内部加锁或修改数据
正确初始化 shared_mutex 和 shared_lock 的典型模式
最简可用结构是把 std::shared_mutex 作为类成员,所有读接口用 std::shared_lock 包裹,写接口用 std::unique_lock。
class DataContainer {
mutable std::shared_mutex rw_mutex_; // mutable 允许 const 成员函数加锁
std::vector<int> data_;
<p>public:
int get_size() const {
std::shared_lock<std::shared_mutex> lock(rw<em>mutex</em>); // 自动 RAII
return static<em>cast<int>(data</em>.size());
}</p><pre class="brush:php;toolbar:false;">void append(int x) {
std::unique_lock<std::shared_mutex> lock(rw_mutex_);
data_.push_back(x);
}};
立即学习“C++免费学习笔记(深入)”;
-
rw_mutex_必须声明为mutable,否则const成员函数里无法调用其lock_shared() -
std::shared_lock构造即加锁,析构即释放,别手动调用lock()/unlock() - 不要跨作用域传递
std::shared_lock对象——移动后原对象处于未持有状态,再用会 UB
shared_lock 不支持升级为写锁,需要显式切换
这是最容易踩的坑:你不能在持有 std::shared_lock 的前提下,“顺便”改成写操作。C++ 标准明确禁止锁升级(避免死锁),必须先释放读锁,再获取独占锁。
典型误写:std::shared_lock lk(mtx); if (need_write) { std::unique_lock ulk(mtx); /* … */ } —— 这会造成两次加锁,且中间存在竞态窗口。
- 如果读完发现要写,必须先让
std::shared_lock离开作用域(或显式lk.unlock()),再构造std::unique_lock - 更稳妥的做法是:预判场景,直接上
std::unique_lock;或用双重检查(read-lock → 判断 → drop → write-lock) - 某些场景可用
std::shared_mutex::try_lock_shared()配合重试,但别滥用——失败后忙等会伤性能
Windows 上 VS2019/2022 默认不启用 C++17 共享锁,需确认编译器设置
VS 默认项目模板仍用 C++14,即使写了 #include <shared_mutex></shared_mutex>,也会报错 std::shared_mutex is not a type 或链接失败。
- MSVC 中必须开启
/std:c++17或更高(项目属性 → C/C++ → 语言 → C++ 语言标准) - MinGW-w64 需 GCC 8+ 且定义
_GLIBCXX_CONCEPTS(通常默认已开) - Clang 需
-std=c++17,且注意 libc++ 对shared_mutex的实现晚于 libstdc++,建议用较新版本
没有正确启用 C++17 时,std::shared_lock 可能静默退化为普通互斥行为(比如只允许一个读者),但不会编译报错——这会让问题更隐蔽。


















