std::mutex不支持同线程重复加锁,否则导致未定义行为;std::recursive_mutex允许同线程多次加锁并计数管理,仅在明确需要重入时选用,优先使用更轻量安全的std::mutex。

std::mutex 是普通互斥锁,不支持同一线程重复加锁
它是最基础的互斥机制,一旦线程成功调用 lock(),再次调用就会导致**未定义行为**(通常是死锁或程序崩溃)。这符合“一个锁、一次持有”的设计原则,适合保护临界资源且逻辑清晰的场景。
例如:一个函数内部加锁后调用另一个也试图加同一把锁的函数,用 std::mutex 就会出问题:
- funcA() → lock(mtx) → funcB() → lock(mtx) ❌ 崩溃或死锁
std::recursive_mutex 允许同一线程多次加锁,但需对应次数解锁
它内部维护一个**持有计数器**和**持有线程ID**。同一线程反复调用 lock() 会递增计数;每次 unlock() 减一;只有计数归零时才真正释放锁。适合递归调用、重入式设计或封装层次较深的代码。
注意:跨线程仍互斥,只是放宽了同一线程的限制。使用不当容易掩盖设计缺陷,比如隐藏了本该用不同锁或重构逻辑的问题。
立即学习“C++免费学习笔记(深入)”;
选择建议:优先用 std::mutex,仅在明确需要重入时选 recursive_mutex
多数情况下,std::mutex 更轻量、更安全、更易排查问题。C++ 标准库中绝大多数容器和工具都基于非递归锁设计。
- 如果你能通过调整函数职责、拆分临界区、或用 RAII(如 std::lock_guard)避免重复加锁 → 用 std::mutex
- 如果确实存在合法递归调用(如解析嵌套表达式、事件回调再触发自身),且难以重构 → 可考虑 std::recursive_mutex
- 性能上,recursive_mutex 有额外计数和判断开销,虽然微小,但非必要不引入
别忽略替代方案:可重入 ≠ 必须用 recursive_mutex
有时你以为需要重入,其实只是锁粒度或设计不合理。可以尝试:
- 把大锁拆成多个细粒度锁,降低冲突和嵌套需求
- 用 std::shared_mutex(C++17)区分读写,提升并发性
- 用 std::scoped_lock 或 std::unique_lock 配合 try_lock 等灵活控制
- 用无锁结构(如原子变量、lock-free queue)替代部分锁场景
基本上就这些。选对锁不是炫技,而是让多线程逻辑更清晰、更可靠、更容易维护。










