问题:
- 虚假唤醒
虚假唤醒 : 先调用了唤醒,再调用等待,是一次无效的操作,同时会使得等待无法唤醒
解决办法:
- 自定义等待计数和唤醒计数,初始化为0
- 设置条件变量线程间通信
std::condition_variable _cv; // 阻塞等待 条件变量
int _wait = 0; // 等待计数
int _wakeup = 0; // 唤醒计数
// 等待
void waitForCall()
{
// 加锁避免多线程冲突
std::unique_lock<std::mutex> lock(_mutex);
// 进入等待计数
if(--_wait <= 0)
{
// 阻塞等待 等待唤醒计数 > 0
_cv.wait(lock, [this]()->bool{
return _wakeup > 0;
})
// 已唤醒 唤醒计数减一
--_wakeup;
}
}
// 唤醒
void wakeUp()
{
// 可能多个线程都在等待,所以只有当 自加 之后仍然 <= 0 才能开始唤醒
// 避免了虚假唤醒
if(++_wait <= 0)
{
// 唤醒 唤醒计数 +1
++_wakeup;
// 条件变量开始唤醒
_cv.notify_one();
}
}