我写了一个按以下方式工作的计时器:
使用timer的类实现了一个回调函数call_()
。
计时器在单独的线程中运行,并在计时器到期时执行call_()
。
我的测试程序如下:
void TestCase::loop()
{
unique_lock<mutex> lock(*this);
while(running_)
{
timer_->SetTimer(time);
signal_.wait(lock);
do_something();
}
}
void TestCase::call_()
{
signal_.notify_all();
}
如果time
非常小(例如2ms),测试程序有时会执行do_something()
,有时则不执行(在测试程序的不同运行中)。
我的猜测是竞争条件,似乎time
很小call()_
在signal_.notify_all()
之前执行(signal_.wait(lock)
}。
如果我在this_thread::sleep(posix_time::milliseconds(2))
之前添加signal_.notify_all()
,
几乎每次运行都会执行do_something()
,sleep(5)
一切正常。
如何确保在signal_.wait(lock)
之前执行signal_.notify_all()
?
答案 0 :(得分:1)
如果超时值非常小,则无法保证主线程在定时器线程执行signal_wait
语句之前到达signal_.notify_all
语句。
当您使用一次性计时器时,更好的选择是使用信号量而不是条件变量来同步两个线程。
正如您在条件变量中看到的那样,为了使机制正常工作,必须执行wait和notify。
使用信号量,执行等待的线程也将停止,直到另一个线程发布信号量,但不要求以何种顺序执行等待和后续操作。如果首先到达帖子,则等待立即返回(并且成功)。