关于使用条件变量、事件来唤醒等待线程的坑
习惯性思维很容易导致一些常见性的错误,而且还很难发现。
前言
以前使用windows的Event事件习惯了,在多线程竞争消费数据时,也继续使用了Event来通知唤醒等待线程。
后来写跨平台代码的时候,也惯例的使用条件变量来做同样的事情。
甚至,后来自己写通信框架的时候也沿用这种做法。
Bug现象
我常常使用一个队列存放消息,然后把消息数据压入队列,然后用一个内核对象(Event或条件变量)来触发信号;
后面用几个线程wait这个内核对象,等待到该内核对象有信号,就从队列中获取消息并消费,在实际的代码使用中,曾经很奇怪的出现某些消息处理耗时很长的问题,一直没有往Event和条件变量方面的问题上想,通过几个改动,bug现象消失了,然后就搁置了,毕竟工作太多。
伪代码的逻辑大约如下:
void PushMessage(void *pMes)
{
lock.Lock();
messageQueue.push(pMes);
event.SetEvent();
lock.UnLock();
}
//work thread:
void WaitMessage()
{
if(event.wait()==0)
{
do
{
void *pMes = NULL;
lock.Lock();
if(messageQueue.size()>0)
{
pMes = messageQueue.front();
messageQueue.pop();
}
lock.U