Boost :: Thread / C ++ 11 std :: thread,想要在条件下唤醒工作线程

时间:2013-11-24 23:35:47

标签: c++ multithreading boost c++11

我使用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时进入休眠状态。问题是存在竞争条件。以下是一个示例情况:

  1. 工作线程评估是否(a == b),发现它是真的。
  2. 主线程更改a和/或b,使它们不再相等。在工作线程上调用notify_one()。
  3. 工作线程忽略notify_one(),因为它仍处于唤醒状态。
  4. 工作线程进入睡眠状态。 死锁
  5. 如果我可以避免条件变量,那会更好,因为我实际上不需要锁定任何东西。但只要让工作线程在== b时进入休眠状态,并且只要!= b就唤醒。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:4)

您似乎未正确同步访问权限:当您在工作线程中阅读ab时,至少在访问与之共享的值时,您需要获取锁定生产者:由于工作线程持有锁,主线程不能更改ab。如果它们不相等,则工作线程可以释放锁并且流失处理值。如果它们相等,那么工作线程将wait()放在条件变量上,而则保持锁定!条件变量的主要功能是以原子方式释放锁并进入休眠状态。

当主线程更新a和/或b时,它获取锁定,进行更改,释放锁定并通知工作线程。工作线程显然没有持有锁,但是在下一次检查到期或通知结果时获取它,检查值的状态和wait() s或处理值。

正确完成后,没有竞争条件的可能性!

我错过了你的关键混乱:“因为我实际上不需要锁定任何东西”!好吧,当你有两个同时可以访问相同值的线程,并且至少其中一个正在修改该值时,如果没有同步,则会有数据竞争。任何具有数据竞争的程序都有未定义的行为。换句话说:即使您只想从一个线程向另一个线程发送bool值,您也需要同步。同步不必采用锁的形式(例如,可以使用原子变量来同步值)但是进行非平凡的通信,例如,涉及两个int而不是仅包含一个原子变量,通常是挺难的!你几乎肯定希望使用锁。然而,你可能还没有发现这种深刻的欲望。

答案 1 :(得分:0)

要考虑的事情:

  1. 您的线程是否有理由保持睡眠状态?
  2. 为什么不启动新线程并让它在完成工作后死于自然死亡?
  3. 如果在任何时间点只有一个代码路径处于活动状态(所有其他线程都处于休眠状态),那么您的设计不允许并发。
  4. 最后,如果您使用的是线程之间共享的变量,那么您应该使用atomics。这将确保同步对您的值的访问。