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

Boost::Thread / C++11 std::thread, want to wake worker thread on condition

本文关键字:线程 唤醒 工作 条件 thread C++11 std Boost      更新时间:2023-10-16

我正在使用Boost::thread作为worker线程。 我想在没有工作要做时让工作线程进入睡眠状态,并在有工作要做时立即唤醒它。 我有两个保存整数的变量。 当整数相等时,无需执行任何工作。 当整数不同时,有工作要做。 我当前的代码如下所示:

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

我尝试使用条件变量并在 a == b 时让工作线程进入睡眠状态。 问题是存在竞争条件。 下面是一个示例情况:

  1. 工作线程计算 if(a == b(,发现它是真的。
  2. 主线程更改 a 和/或 b,使它们不再相等。 在工作线程上调用 notify_one((。
  3. 工作线程忽略 notify_one((,因为它仍处于唤醒状态。
  4. 工作线程进入睡眠状态。僵局

更好的是,如果我能避免条件变量,因为我实际上不需要锁定任何东西。 但是只要让工作线程在 a == b 时进入睡眠状态,并在 a != b 时唤醒。 有没有办法做到这一点?

您似乎没有正确同步您的访问: 当您在工作线程中读取ab时,至少在访问与生产者共享的值时,您需要获取一个锁: 由于工作线程持有锁,主线程无法更改ab。如果它们不相等,则工作线程可以释放锁并处理值。如果它们相等,则在按住锁,工作线程将wait()条件变量上!条件变量的主要功能是以原子方式释放锁并进入睡眠状态。

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

如果操作正确,则没有竞争条件的可能性!

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

需要考虑的事情:

  1. 你的线程有理由保持睡眠状态吗?
  2. 为什么不启动一个新线程,让它在完成工作后自然死亡呢?
  3. 如果在任何时间点只有一个代码路径处于活动状态(所有其他线程都处于休眠状态(,则您的设计不允许并发。

最后,如果您使用的是线程之间共享的变量,则应使用原子组学。这将确保对值的访问是同步的。