Files
CWithClasses/Thread/Mutex.md
2025-12-31 12:49:32 +08:00

4.7 KiB
Raw Permalink Blame History

哈哈,好,这一波咱把 <mutex> 彻底端了 😄 你现在这个节奏是对的:thread 看清 → mutex 看透 → 并发就不怕了

我给你的是一份 能当“并发速查表”的 <mutex> 全家桶说明,照着用不翻车。


一、<mutex> 是干嘛的?一句话版

<mutex> 负责“同步”,不负责“并发”。

  • thread:开人
  • mutex:防抢
  • atomic:小件快递
  • future:结果回收

二、std::mutex(最常用)

1 std::mutex

#include <mutex>

std::mutex m;

作用

  • 最普通的互斥锁
  • 同一时间只能一个线程进入临界区

2 lock() —— 上锁(阻塞)

m.lock();
// 临界区
m.unlock();

特点

  • 如果锁被占用 → 阻塞等待
  • 不可递归

返回值

新手警告

一旦忘记 unlock(),程序直接死锁


3 unlock() —— 解锁

m.unlock();

返回值


4 try_lock() —— 尝试上锁(不阻塞)

if (m.try_lock()) {
    // 拿到锁
    m.unlock();
}

返回值

  • true:成功
  • false:失败

用途

  • 避免卡死
  • 非关键任务

三、RAII 锁(你真正该用的

99% 的情况下,不要直接用 lock()/unlock()


5 std::lock_guard(最常用、最安全)

void foo(){
    std::lock_guard<std::mutex> lock(m);
    // 自动上锁
    // 自动解锁(作用域结束)
}

特点

  • 构造时上锁
  • 析构时解锁
  • 不能手动 unlock

返回值

✔ 最安全 ✔ 最推荐


6 std::unique_lock(高级版)

std::unique_lock<std::mutex> lock(m);

特点

  • 可以:

    • 延迟上锁
    • 手动 unlock / lock
    • 搭配 condition_variable

常见用法

std::unique_lock<std::mutex> lock(m);
lock.unlock();
// ...
lock.lock();

返回值

📌 灵活 ≠ 常用,新手少用


7 延迟上锁

std::unique_lock<std::mutex> lock(m, std::defer_lock);
// 之后再 lock()
lock.lock();

8 尝试上锁(不阻塞)

std::unique_lock<std::mutex> lock(m, std::try_to_lock);
if (lock.owns_lock()) {
    // 成功
}

四、特殊 mutex 类型

9 std::recursive_mutex

std::recursive_mutex m;

特点

  • 同一线程可以多次 lock
  • 必须 unlock 相同次数

什么时候用?

  • 递归函数
  • 老代码

⚠️ 能不用就不用,通常是设计有问题


🔟 std::timed_mutex

std::timed_mutex m;

作用

  • 支持超时锁
if (m.try_lock_for(100ms)) {
    m.unlock();
}

11 std::recursive_timed_mutex

= recursive_mutex + 超时


五、一次锁多个 mutex死锁克星

12 std::lock()

std::lock(m1, m2);
// 全部锁成功

特点

  • 避免死锁
  • 要么全拿,要么全不拿

13 std::scoped_lockC++17

std::scoped_lock lock(m1, m2);

✔ 自动 ✔ 安全 ✔ 推荐


六、完整 API 总表(收藏级)

API 作用 返回值
mutex 基础互斥锁
lock() 阻塞上锁 void
unlock() 解锁 void
try_lock() 尝试上锁 bool
recursive_mutex 可递归锁
timed_mutex 超时锁
recursive_timed_mutex 递归+超时
lock_guard RAII 锁
unique_lock 高级 RAII 锁
scoped_lock 多锁 RAII
lock() 同时锁多个 mutex void

七、什么时候用 mutex一句判断法

如果一个变量:

  • 被多个线程访问
  • 至少一个线程写

👉 要么 mutex要么 atomic


八、什么时候不要用 mutex

只是计数 简单 flag 单一整数状态

👉atomic,更快更简单。


九、新手不翻车口诀(记住这 4 句)

1 能不共享就不共享 2 能分任务就别加锁 3 能用 lock_guard 就别手写 lock 4 看到 recursive_mutex 先怀疑设计


你现在已经把 thread + mutex 两大核心吃下来了。 下一步顺序我强烈建议:

👉 <atomic>(最后一块拼图) 或者 👉 condition_variable(线程协作)

你选一个,我继续给你“端锅”。