std::scoped_lock 能同时锁多个互斥量,这是其相比 std::lock_guard 的核心改进;它通过内部调用 std::lock 算法确保全局一致加锁顺序,从根本上避免死锁。
std::scoped_lock 能否同时锁多个互斥量
可以,而且这是它相比 std::lock_guard 最核心的改进点。C++17 引入 std::scoped_lock 的主要目的,就是安全、简洁地一次性锁定多个 std::mutex(或任何满足 Lockable 概念的对象),并自动避免死锁。
为什么用 std::scoped_lock 而不是多次 new lock_guard
手动对多个 mutex 逐个调用 lock() 极易引发死锁——比如线程 A 先锁 m1 再锁 m2,线程 B 反过来先锁 m2 再锁 m1,就可能卡住。而 std::scoped_lock 内部使用 std::lock 算法(基于试探性加锁 + 退避重试),保证所有传入的 mutex 以**全局一致的顺序**被锁定,从而从根源上消除这种死锁可能。
常见错误现象:
– 手写 m1.lock(); m2.lock(); 导致程序偶发 hang 住
– 用两个 std::lock_guard 分别构造,编译直接报错(因为 std::lock_guard 不支持多参数构造)
正确做法:
std::mutex m1, m2, m3; // ✅ 一行搞定,自动防死锁,离开作用域自动 unlock std::scoped_lock lk(m1, m2, m3); // ... 临界区操作
std::scoped_lock 的参数和类型约束
它接受任意数量(≥1)的可锁定对象,但所有参数必须满足 Lockable 概念(std::mutex、std::recursive_mutex、std::shared_mutex 等都符合)。不支持混合类型指针/引用混用;所有参数应为左值(或能绑定到左值引用的临时量,但一般不建议传临时 mutex)。
立即学习“C++免费学习笔记(深入)”;