std::shared_mutex、std::mutex和std::recursive_mutex是什么锁

std::shared_mutex。std::mutex和std::recursive_mutex是什么锁

锁类型 类型 核心特性 适用场景
std::shared_mutex 读写锁 读共享、写独占 读多写少
std::mutex 普通互斥锁 完全独占,不可递归 通用场景(90%的情况)
std::recursive_mutex 递归互斥锁 同一线程可重复加锁 递归函数、嵌套调用

详细对比

1. std::shared_mutex ------ 读写锁(C++17)
特性 说明
读模式 多个线程可同时持有共享锁,并发读取
写模式 只有一个线程可持有独占锁,写时禁止任何读
适用场景 读多写少(如配置缓存、路由表、DNS缓存)
性能 读并发高,但写操作开销比 mutex
RAII工具 std::shared_lock(读)、std::unique_lock(写)
cpp 复制代码
std::shared_mutex rw_mutex;
std::map<int, int> cache;

// 读操作:多个线程可并发
int read(int key) {
    std::shared_lock lock(rw_mutex);  // 共享锁
    return cache[key];
}

// 写操作:独占
void write(int key, int val) {
    std::unique_lock lock(rw_mutex);  // 独占锁
    cache[key] = val;
}
2. std::mutex ------ 普通互斥锁(C++11)
特性 说明
独占性 完全独占,同一时间只有一个线程能持有
递归 不支持,同一线程重复 lock() 会导致死锁
适用场景 90%的常规多线程场景
性能 最基础、性能最高
RAII工具 std::lock_guardstd::unique_lock
cpp 复制代码
std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard lock(mtx);  // 自动加锁解锁
    ++counter;
}
3. std::recursive_mutex ------ 递归互斥锁(C++11)
特性 说明
独占性 独占,但同一线程可重复加锁
递归 支持,内部维护计数器,加锁几次就要解锁几次
适用场景 递归函数、嵌套调用中需要加锁的场景
性能 mutex 略低(需维护线程ID和计数)
注意 容易掩盖设计缺陷,能不用就不用
cpp 复制代码
std::recursive_mutex rec_mtx;

void funcA() {
    std::lock_guard lock(rec_mtx);  // 第一次加锁
    funcB();                        // 内部再次加锁,不会死锁
}

void funcB() {
    std::lock_guard lock(rec_mtx);  // 第二次加锁(同一线程)
}

对比总结

维度 std::mutex std::recursive_mutex std::shared_mutex
C++版本 C++11 C++11 C++17
独占性 ✅ 独占 ✅ 独占 ✅ 写独占,❌ 读共享
递归 ❌ 不支持 ✅ 支持 ❌ 不支持
读并发 ❌ 不支持 ❌ 不支持 ✅ 支持
性能 最高 略低 读场景高,写场景低
RAII工具 lock_guard / unique_lock lock_guard / unique_lock shared_lock(读) / unique_lock(写)
适用场景 通用 递归/嵌套调用 读多写少

选择建议

  1. 默认首选std::mutex + std::lock_guard
  2. 读多写少std::shared_mutex + std::shared_lock(读)/ std::unique_lock(写)
  3. 递归调用std::recursive_mutex(但优先考虑重构代码避免递归加锁)
相关推荐
罗西的思考9 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队13 小时前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
用户8055336980319 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
To_OC1 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC1 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK1 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境2 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
_清歌2 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局2 天前
SVD 的三步走:双对角化、Givens 收敛、排序
算法