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

多线程使用std::unique_lock抛出Resource deadlock avoided错误如何解决?

问题原因

核心问题出在sendCommand函数里互斥锁的错误使用逻辑:

  • 你在构造unique_lock时已经传入了std::try_to_lock参数,这个阶段unique_lock已经自动调用了一次_writeMtx.try_lock()尝试加锁
  • 紧接着你又手动调用了一次lock.try_lock(),而std::mutex属于非递归互斥锁,同一个线程对已经持有的非递归互斥锁重复执行加锁操作(包括try_lock)属于未定义行为,GNU libstdc++的实现会直接抛出std::system_error,错误描述就是Resource deadlock avoided
  • 额外逻辑漏洞:当前代码不管加锁是否成功,都会直接执行_serial.writeString,完全没有起到互斥保护的作用,会引发串口写操作并发冲突。

修复方案

修改sendCommand中互斥锁的使用逻辑,二选一即可:

方案1:使用阻塞加锁逻辑(推荐)

串口写入耗时极短,阻塞加锁几乎不会影响业务性能,代码最简洁稳定:

int DASEmulator::sendCommand(const QString &command)
{
    QString fullCommand = "**" + command + ';';
    qDebug() << "Sending" << fullCommand ;
    char e{};
    {
        unique_lock<mutex> lock{_writeMtx};
        e = _serial.writeString(fullCommand.toLatin1());
    }
    if (e!=1)
        cerr << "writeString error: " << e << endl;
    else
        qDebug() << "Sent: " << fullCommand ;
    return (int)e;
}

方案2:保留非阻塞加锁逻辑

如果确实需要非阻塞的加锁判断,直接判断构造后的锁持有状态即可,不要额外调用try_lock,同时加锁失败要跳过写入操作避免并发问题:

int DASEmulator::sendCommand(const QString &command)
{
    QString fullCommand = "**" + command + ';';
    qDebug() << "Sending" << fullCommand ;
    char e{};
    {
        unique_lock<mutex> lock{_writeMtx, std::try_to_lock};
        if (!lock.owns_lock()) {
            cout << "Could not acquire lock" << endl;
            e = -1; // 自定义错误码标识加锁失败
        } else {
            e = _serial.writeString(fullCommand.toLatin1());
        }
    }
    if (e!=1)
        cerr << "writeString error: " << e << endl;
    else
        qDebug() << "Sent: " << fullCommand ;
    return (int)e;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:54:01