C++中lock_guard怎么用_C++多线程自动加锁解锁机制【并发】

2次阅读

lock_guard 是上自动管理互斥量生命周期的 RaiI 类模板,构造时加锁、析构时解锁,确保异常安全;不能 new、不能 return、不能作类成员,因其禁止拷贝/移动且依赖栈对象生命周期。

C++中lock_guard怎么用_C++多线程自动加锁解锁机制【并发】

lock_guard 是什么,为什么不能直接 new 或 return

lock_guard 是一个上自动管理互斥量生命周期的 RAII 类模板,它在构造时加锁、析构时解锁。它的核心价值不是“加锁”,而是“确保锁一定被释放”——哪怕中间抛异常、提前 return 或 goto 跳出作用域析构函数仍会被调用。

所以你不能:
new lock_guard(m)分配对象不会自动析构
return lock_guard(m):返回临时对象会触发移动/拷贝,而 lock_guard 明确删除了拷贝和移动构造函数(编译报错:use of deleted function
– 把它作为类成员变量长期持有:它不拥有 mutex,也不负责管理其生命周期,只管“这一段代码执行期间”的锁定

最常用写法:在作用域开头声明,配合 std::mutex 使用

典型场景是保护共享数据读写。比如多个线程往同一个 std::vector 里 push:

std::mutex mtx; std::vector data; 

void thread_func() { // 加锁范围仅限于访问 data 的这几行 std::lock_guard guard(mtx); data.push_back(42); // guard 离开作用域,自动 unlock() }

注意:
guard 必须声明在需要保护的代码之前,且作用域要严格包裹临界区
– 不要手动调用 guard.unlock():它没这个接口,也不该有
– 如果临界区很长或包含可能 throw 的操作,lock_guard 依然安全

和 unique_lock 对比:什么时候不该用 lock_guard

lock_guard 是最轻量、最严格的自动锁,但灵活性差。遇到以下情况,就得换 std::unique_lock

  • 需要延迟加锁(构造时不锁,后面再 lock()
  • 需要手动控制解锁时机(比如先 unlock 再做耗时 IO,避免阻塞其他线程)
  • 要和条件变量 std::condition_variable 配合使用(wait() 要求传入 unique_lock
  • 要转移锁的所有权(比如放进 std::move 返回值中)

lock_guard 没有 unlock()try_lock()release() 这些方法,也没提供底层 mutex* 访问接口——它就是为“进作用域即锁、出作用域即放”这个单一语义设计的。

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

容易忽略的细节:类型必须匹配,且 mutex 不能是临时对象

lock_guard 模板参数类型必须和传入的互斥量类型完全一致。常见错误:

std::recursive_mutex rm; std::lock_guard guard(rm); // ❌ 编译失败:类型不匹配

正确写法是:

std::lock_guard guard(rm); // ✅

另一个坑是传入临时 mutex

std::lock_guard guard(std::mutex{}); // ❌ 构造完就销毁 mutex,guard 锁的是已析构对象

所有 mutex 实例必须是静态、全局、类成员或栈上持久存在的对象。

text=ZqhQzanResources