我使用Boost :: thread作为工作线程。我想在没有工作要做的时候让工作线程进入睡眠状态,并在有工作要做的时候立即将其唤醒。我有两个包含整数的变量。当整数相等时,没有工作要做。当整数不同时,还有工作要做。我目前的代码如下:
int a;
int b;
void worker_thread()
{
while(true) {
if(a != b) {
//...do something
}
//if a == b, then just waste CPU cycles
}
}
//other code running in the main thread that changes the values of a and b
我尝试使用条件变量并让工作线程在== b时进入休眠状态。问题是存在竞争条件。以下是一个示例情况:
如果我可以避免条件变量,那会更好,因为我实际上不需要锁定任何东西。但只要让工作线程在== b时进入休眠状态,并且只要!= b就唤醒。有没有办法做到这一点?
答案 0 :(得分:4)
您似乎未正确同步访问权限:当您在工作线程中阅读a
和b
时,至少在访问与之共享的值时,您需要获取锁定生产者:由于工作线程持有锁,主线程不能更改a
和b
。如果它们不相等,则工作线程可以释放锁并且流失处理值。如果它们相等,那么工作线程将wait()
放在条件变量上,而则保持锁定!条件变量的主要功能是以原子方式释放锁并进入休眠状态。
当主线程更新a
和/或b
时,它获取锁定,进行更改,释放锁定并通知工作线程。工作线程显然没有持有锁,但是在下一次检查到期或通知结果时获取它,检查值的状态和wait()
s或处理值。
正确完成后,没有竞争条件的可能性!
我错过了你的关键混乱:“因为我实际上不需要锁定任何东西”!好吧,当你有两个同时可以访问相同值的线程,并且至少其中一个正在修改该值时,如果没有同步,则会有数据竞争。任何具有数据竞争的程序都有未定义的行为。换句话说:即使您只想从一个线程向另一个线程发送bool
值,您也需要同步。同步不必采用锁的形式(例如,可以使用原子变量来同步值)但是进行非平凡的通信,例如,涉及两个int
而不是仅包含一个原子变量,通常是挺难的!你几乎肯定希望使用锁。然而,你可能还没有发现这种深刻的欲望。
答案 1 :(得分:0)
要考虑的事情:
最后,如果您使用的是线程之间共享的变量,那么您应该使用atomics。这将确保同步对您的值的访问。