周五半天加晚上到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(); // 死锁
}
}