c++中的std::unique_lock是什么_c++与lock_guard的区别与使用【多线程】

2次阅读

std::unique_lock比std::lock_guard更灵活但更易出错:前者支持延迟加锁、手动锁控、所有权转移及配合条件变量,后者仅适用于构造即锁、析构即锁的简单场景。

c++中的std::unique_lock是什么_c++与lock_guard的区别与使用【多线程】

std::unique_lockc++11 引入的可移动(moveable)、可延迟加锁、可手动控制加锁/解锁时机的互斥量包装器,比 std::lock_guard 更灵活,但也更易出错。

核心区别:灵活性 vs 简单性

两者都用于 RaiI 方式管理互斥量(如 std::mutex),但设计目标不同:

  • std::lock_guard:构造即加锁,析构即解锁,不可复制、不可移动,生命周期绑定严格,适合“进作用域就锁、出作用域就放”的简单场景。
  • std::unique_lock:构造时可选择不加锁(std::defer_lock),支持手动调用 lock()/unlock(),支持转移所有权(move),还能配合 std::condition_variable 等高级同步原语。

常见使用场景对比

用 lock_guard 的时候: 只在某段代码块内保护临界区,不需要中途释放锁、也不需要条件等待。

std::mutex mtx; void safe_increment() {     std::lock_guard<std::mutex> lk(mtx); // 构造即锁     ++counter;                            // 临界区 } // 析构自动解锁 —— 简洁安全

必须用 unique_lock 的时候:

  • 需要延迟加锁(比如先做检查再决定是否加锁)
  • 要和 std::condition_variable::wait() 配合(wait 要求锁可手动释放并重获)
  • 需要在函数内多次加锁/解锁(例如分阶段处理)
  • 要把锁的所有权转移到另一个作用域(如返回一个带锁的资源)

典型 unique_lock 用法示例

✅ 延迟加锁:

c++中的std::unique_lock是什么_c++与lock_guard的区别与使用【多线程】

Magick

无代码AI工具,可以构建世界级的AI应用程序。

c++中的std::unique_lock是什么_c++与lock_guard的区别与使用【多线程】 225

查看详情 c++中的std::unique_lock是什么_c++与lock_guard的区别与使用【多线程】

立即学习C++免费学习笔记(深入)”;

std::unique_lock<std::mutex> lk(mtx, std::defer_lock); if (need_to_modify()) {     lk.lock();   // 按需加锁     update_data();     lk.unlock(); // 可提前释放 } // lk 析构时若仍持有锁,会自动释放

✅ 配合条件变量:

std::mutex mtx; std::condition_variable cv; bool ready = false;  // 等待线程: std::unique_lock<std::mutex> lk(mtx); cv.wait(lk, []{ return ready; }); // wait 内部会自动 unlock + 重新 lock // 继续执行时 lk 一定已重新加锁

注意事项

  • 不要对同一个 unique_lock 多次调用 lock()(未解锁时再 lock 会死锁)
  • 手动 unlock() 后不要再访问被保护的数据,除非你明确知道其他线程不会修改它
  • 避免把 unique_lock 当成“更高级的 lock_guard”滥用 —— 复杂性带来维护成本
  • 如果只是保护一段短小临界区,优先选 lock_guard;只有真需要它的特性时才用 unique_lock

基本上就这些。选哪个不是看“谁更新”,而是看“你的同步逻辑是否需要它提供的控制力”。

text=ZqhQzanResources