线程同步+锁内嵌套回调引发死锁

周五半天加晚上到9点半,周六一天,周一早上7点半到10点,快折腾出人命了,终于把原来别人写的socket网络通讯类给重构了。

  问题比较奇葩,表现是一般情况正常,偶尔突发情况下ui线程卡死,于是都没在意。直到这次新功能添加断线重连后,重连 必卡死,一开始还以为我添加的重连逻辑有问题,各种改各种测试,无效。后来一看俩socket管理类我就哭了…重构代码才发现是逻辑问题导致的死锁…两个类一个三条另一个一条共四条常驻while(true)线程,外带n套锁…跟进锁匠铺似的伤不起啊…藏在多线程下偷偷在锁里调回调…我也是醉了…

  出问题的代码类似下面的结构:

std::mutex _locker1;
std::list<> _list1;
std::mutex _locker2;
std::list<> _list2;

...
// 主线程调用
bool ClassA::func_main_thread()
{
    bool success = true;
    _locker1.lock();
    {
        ...
        _list1 ...
        if (...) {
            success = false;
        }
    }
    _locker1.unlock();

    if (!success) return false;

    _locker2.lock();
    {
        ...
        _list2 ...
    }
    _locker2.unlock();

    return success;
}

// 轮询工作线程1
void ClassA::fun_work_thread_1()
{
    while(run) {
        _locker1.lock();
        {
            ...
            _list1 ...
            _locker2.lock();
            {
                ...
                _list2 ...
            }
            _locker2.unlock();  
        }
        _locker1.unlock();
        }
    }
}

// 轮询工作线程2
void ClassA::fun_work_thread_2()
{
    while(run) {
        _locker2.lock();
        {
            ...
            for (iter in _list2) {
                callback(iter); //-----锁内嵌套回调
            }
        }
        _locker2.unlock();  
    }
}

// 回调
callback(iter)
{
    if (success) {
    }
    else {
        func_main_thread(); // 死锁
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值