You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scoped_lock避免死锁——C++17示例代码技术咨询

如何用std::scoped_lock规避C++中的锁顺序死锁?

嘿,这个问题我太熟了!你遇到的是典型的锁顺序死锁——当两个线程以相反的顺序获取互斥量时,就会卡住互相等待对方释放锁。好在C++17引入的std::scoped_lock就是专门解决这个问题的神器!

先拆解原代码的死锁根源

你给出的deadlock_func_1先锁定mut_a,睡眠100ms后再去锁mut_b;对应的另一个产生死锁的函数(比如deadlock_func_2)应该是先锁mut_b,再尝试锁mut_a。当这两个线程同时运行时:

  • 线程1拿到mut_a,等着拿mut_b
  • 线程2拿到mut_b,等着拿mut_a
    双方都不肯先释放手里的锁,直接陷入死锁。

用std::scoped_lock解决问题的核心逻辑

std::scoped_lock是C++17新增的锁管理器,它支持同时锁定多个互斥量,并且内部会采用避免死锁的算法(比如按互斥量的内存地址排序后再依次锁定)。不管你在不同线程里传入互斥量的顺序如何,它都会用一致的顺序去锁定,从根源上切断死锁的可能。

修改后的完整代码

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
using namespace chrono_literals;

mutex mut_a;
mutex mut_b;

// 修复后的函数1:用scoped_lock同时锁定两个互斥量
static void safe_func_1() {
    cout << "safe f1 acquiring both mutexes..." << endl;
    scoped_lock lock{mut_a, mut_b}; // 一次性锁定,顺序不影响
    this_thread::sleep_for(100ms);
    cout << "safe f1: got both mutexes, doing work..." << endl;
}

// 修复后的函数2:即使传入顺序相反,也不会死锁
static void safe_func_2() {
    cout << "safe f2 acquiring both mutexes..." << endl;
    scoped_lock lock{mut_b, mut_a}; // 顺序和func1相反,但scoped_lock会自动处理
    this_thread::sleep_for(100ms);
    cout << "safe f2: got both mutexes, doing work..." << endl;
}

int main() {
    thread t1(safe_func_1);
    thread t2(safe_func_2);
    t1.join();
    t2.join();
    return 0;
}

额外说明

  • scoped_lock和lock_guard一样,都是RAII风格的锁管理器,会在作用域结束时自动释放所有锁定的互斥量,不用手动解锁。
  • 如果你的编译器还不完全支持C++17,也可以用std::lock函数配合lock_guard(需要用std::adopt_lock标记),但scoped_lock的写法更简洁安全。

内容的提问来源于stack exchange,提问作者jlakes85

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:28:34