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

unique_lock与普通mutex是否会引发死锁?附代码咨询

多线程代码死锁风险分析

核心问题解答:工作线程持mutex2时主线程锁mutex1不会死锁

你担心的场景不会引发死锁——mutex1和mutex2是完全独立的两个互斥量:

  • 工作线程持有的是mutex2,它在执行task时只会请求mutex1,不会再尝试获取mutex2;
  • 主线程在task里只会操作mutex1,不会请求mutex2;
    两者不存在循环等待对方持有的锁的死锁必要条件,所以这部分完全安全。

其他位置的潜在问题(无死锁,但有风险)

你的代码整体不存在死锁,但有几个需要注意的问题:

1. task函数中mutex1的手动解锁存在异常安全风险

task里直接调用mutex1.lock()和mutex1.unlock(),如果buffer++或std::cout操作抛出异常(虽然概率低,但C++标准允许流操作抛异常),mutex1会被永久锁定,导致所有调用task的线程永久阻塞——这不是死锁,但后果和死锁类似。

解决方法:用std::lock_guard或std::unique_lock自动管理锁,确保无论是否抛异常都能解锁:

void task(std::string threadName, int loopmax) {
    for(int i = 0; i < loopmax; i++) {
        std::lock_guard<std::mutex> lock(mutex1); // 构造时锁,析构时自动解锁
        buffer++;
        std::cout << threadName << buffer << "\n";
    }
}

2. 全局变量notify存在数据竞争

工作线程写notify = true,主线程读if(!notify),两者没有同步机制,属于数据竞争,会导致未定义行为——比如主线程可能看不到notify的更新,进入不必要的cv.wait(),或者读取到半更新的值。

解决方法:要么用互斥量保护notify的访问,要么把notify改成原子类型:

std::atomic<bool> notify(false);

3. mutex2的使用逻辑是正常同步,无死锁

工作线程一开始就锁住mutex2,直到线程结束才释放;主线程在执行完两次task后尝试锁mutex2,此时如果工作线程还在运行,主线程会阻塞到mutex2被释放。这是正常的线程同步逻辑,不存在循环等待,不会死锁。

至于你提到的“主线程锁mutex2后调用task,线程不再交互”:因为工作线程被mutex2锁住无法继续执行,只有主线程在操作mutex1,所以自然看不到线程交互,这是执行顺序问题,不是死锁。

总结

你的代码不存在死锁风险,但有异常安全和数据竞争的问题,建议按照上面的方法修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:47:17