std::unique_lock在while(1)循环中无法解锁问题求助
问题分析:std::unique_lock 无法获取锁的原因
核心原因:阻塞式IO导致锁长期被持有
你的StdIn_Reader线程中,在持有stdinMutex的状态下调用了read(0, pman->stdin_command, MAXCLIENTMSG)——这是阻塞式读取标准输入的操作。当没有用户输入时,read会一直卡在这行代码上,此时unique_lock始终持有stdinMutex,不会执行后续的lck.unlock()。
而Manager::CommandShell里的std::unique_lock<std::mutex> lck{stdinMutex};是阻塞式获取锁的逻辑,因为锁被StdIn_Reader线程长期占用,这行代码会一直卡住,永远无法执行到cout << "Inside lock\n";,所以只会输出"Entering lock"。
额外的两个逻辑错误
- 重复解锁+无效访问:
CommandShell里的lck定义在内部{}块中,当块结束时lck会被析构,unique_lock的析构函数会自动调用unlock()。但你在块外又写了lck.unlock();,此时lck已经超出作用域,属于无效内存访问;就算没出作用域,也会导致重复解锁,触发未定义行为。 - 共享变量访问遗漏指针:
CommandShell里直接访问stdin_command,但它是Manager类的成员,需要通过pman->stdin_command访问,原代码漏了指针,属于编译错误。
修复方案
1. 把阻塞IO移到锁外
只在读写共享变量时加锁,避免锁被阻塞IO占用:
void *StdIn_Reader(void *p) { int nbytes; char temp_buf[MAXCLIENTMSG + 1]; // 用临时缓冲区存读入数据 while(1) { // 先做阻塞读,不持有锁 nbytes = read(0, temp_buf, MAXCLIENTMSG); if (nbytes > 0) { temp_buf[nbytes]='\0'; // 仅在修改共享变量时加锁 std::unique_lock<std::mutex> lck{stdinMutex}; strcpy(pman->stdin_command, temp_buf); lck.unlock(); // 可以提前解锁,或依赖析构自动处理 pthread_kill(pman->self_id,SIGUSR2); } } return NULL; }
2. 修正CommandShell的锁逻辑
移除多余的显式解锁,修正共享变量访问方式:
{ cout << "Entering lock\n"; std::unique_lock<std::mutex> lck{stdinMutex}; cout << "Inside lock\n"; if(strlen(pman->stdin_command)){ strcpy(command+strlen(command), pman->stdin_command); } pman->stdin_command[0]='\0'; // 无需显式unlock,unique_lock析构时会自动解锁 }
内容的提问来源于stack exchange,提问作者hcastro
相关产品推荐
相关产品推荐

