std::shared_mutex是C++17引入的读写锁机制,允许多个线程共享读锁、单个线程独占写锁,适用于读多写少场景,需包含头文件并启用C++17,推荐使用std::shared_lock和std::unique_lock进行RAII管理以确保异常安全和防止死锁。

std::shared_mutex 是 C++17 引入的一个同步原语,用于实现高效的读写锁机制。它允许多个线程同时进行读操作(共享访问),但在写操作(独占访问)时只允许一个线程执行,并且会阻塞所有其他读和写线程。这种机制非常适合“读多写少”的场景,比如缓存、配置管理等。
1. std::shared_mutex 基本概念
std::shared_mutex 区分两种锁定模式:- 共享锁(shared lock):多个线程可以同时持有,适用于读操作。
- 独占锁(exclusive lock):仅一个线程能持有,适用于写操作。
2. 头文件与编译要求
使用 std::shared_mutex 需要包含头文件:#include
g++ -std=c++17 your_file.cpp
3. 使用方法示例
下面是一个典型的读写锁使用示例:
#include主函数中启动多个读线程和写线程:#include #include #include #include std::vector data = {1, 2, 3}; std::shared_mutex shm; // 共享互斥量 // 读操作函数 void reader(int id) { shm.lock_shared(); // 获取共享锁 std::cout << "Reader " << id << " sees data: "; for (int d : data) { std::cout << d << " "; } std::cout << "\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟处理时间 shm.unlock_shared(); // 释放共享锁 } // 写操作函数 void writer(int id) { shm.lock(); // 获取独占锁 std::cout << "Writer " << id << " is writing...\n"; data.push_back(id); std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::cout << "Writer " << id << " finished writing.\n"; shm.unlock(); // 释放独占锁 }
int main() {
std::vector threads;
// 启动 5 个读线程
for (int i = 1; i <= 5; ++i) {
threads.emplace_back(reader, i);
}
// 启动 2 个写线程
for (int i = 10; i <= 11; ++i) {
threads.emplace_back(writer, i);
}
// 启动更多读线程
for (int i = 6; i <= 10; ++i) {
threads.emplace_back(reader, i);
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
return 0;
}
输出可能类似(顺序不固定):
Reader 1 sees data: 1 2 3 Reader 2 sees data: 1 2 3 ... Writer 10 is writing... Writer 10 finished writing. Reader 6 sees data: 1 2 3 10 ...
4. 推荐使用 RAII 管理锁
直接调用 lock/unlock 容易出错,建议使用 RAII 封装类自动管理锁的生命周期:- std::shared_lock<:shared_mutex>:用于管理共享锁。
- std::unique_lock<:shared_mutex>:也可用于独占锁,但更常用的是直接用 lock_guard 或 unique_lock 配合普通 mutex。不过 shared_mutex 支持 unique_lock 的独占模式。
void reader(int id) {
std::shared_lock lock(shm); // 自动加共享锁,析构时释放
std::cout << "Reader " << id << " sees data: ";
for (int d : data) {
std::cout << d << " ";
}
std::cout << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} // lock 在这里自动释放
void writer(int id) {
std::unique_lock lock(shm); // 独占锁
std::cout << "Writer " << id << " is writing...\n";
data.push_back(id);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Writer " << id << " finished writing.\n";
} // lock 析构时自动释放
这种方式避免了忘记 unlock 导致死锁的风险,也支持异常安全。
5. 注意事项与最佳实践
使用 std::shared_mutex 时注意以下几点:- 确保读写操作逻辑正确区分:只读用 shared_lock,修改用 unique_lock 或 lock()。
- 避免长时间持有共享锁,否则会阻塞写线程,造成写饥饿。
- 某些平台实现中,shared_mutex 性能开销比普通 mutex 高,应根据实际场景选择是否使用。
- 不能递归加锁:同一个线程重复对 shared_mutex 加共享或独占锁会导致未定义行为。











