最近用c++标准库写生产者消费者模式的线程操作队列,对一些代码感到疑惑。比如下面这个线程函数 中为什么要用 while (m_strSendBuf.empty()) 不直接用if判断,百度了一下果然这里存在一个比较常见的线程问题-虚假唤醒。
void ClientSocketManager::SendThreadProc()
{
while (!m_bStop)
{
std::unique_lock<std::mutex> guard(m_mtSendBuf);
while (m_strSendBuf.empty())
{
if (m_bStop)
{
return;
}
m_cvSendBuf.wait(guard);
}
}
}
我的理解就是说处于等待的添加变量可以通过notify_one/notify_all进行唤醒,调用函数进行信号的唤醒时,处于等待的条件变量会重新进行互斥锁的竞争。没有得到互斥锁的线程就会发生等待转移,从等待信号量的队列中转移到等待互斥锁的队列中,一旦获取到互斥锁的所有权就会接着向下执行,但是此时其他线程已经执行并重置了执行条件,这时候该线程下面执行的代码可能引发未定义的错误。