Boost::线程 / C++11 std::thread,想要唤醒工作线程的条件
Boost::Thread / C++11 std::thread, want to wake worker thread on condition
我正在使用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 时让工作线程进入睡眠状态。 问题是存在竞争条件。 下面是一个示例情况:
- 工作线程计算 if(a == b(,发现它是真的。
- 主线程更改 a 和/或 b,使它们不再相等。 在工作线程上调用 notify_one((。
- 工作线程忽略 notify_one((,因为它仍处于唤醒状态。
- 工作线程进入睡眠状态。僵局
更好的是,如果我能避免条件变量,因为我实际上不需要锁定任何东西。 但是只要让工作线程在 a == b 时进入睡眠状态,并在 a != b 时唤醒。 有没有办法做到这一点?
您似乎没有正确同步您的访问: 当您在工作线程中读取a
和b
时,至少在访问与生产者共享的值时,您需要获取一个锁: 由于工作线程持有锁,主线程无法更改a
和b
。如果它们不相等,则工作线程可以释放锁并处理值。如果它们相等,则在按住锁时,工作线程将wait()
条件变量上!条件变量的主要功能是以原子方式释放锁并进入睡眠状态。
当主线程更新a
和/或b
时,它会获取锁、执行更改、释放锁并通知工作线程。工作线程显然没有持有锁,但在下一次检查到期时或作为通知的结果获取它,检查值的状态并wait()
或处理值。
如果操作正确,则没有竞争条件的可能性!
我错过了您的密钥混淆:"因为我实际上不需要锁定任何东西"!好吧,当您有两个线程可以同时访问相同的值并且至少其中一个正在修改该值时,如果没有同步,您就会进行数据争用。任何具有数据争用的程序都具有未定义的行为。换句话说:即使你只想将bool
值从一个线程发送到另一个线程,你也需要同步。同步不必采取锁的形式(例如,可以使用原子变量同步值(,但是进行非平凡的通信,例如,涉及两个int
而不是一个原子通常非常困难!您几乎肯定想使用锁。然而,你可能还没有发现这种深切的愿望。
需要考虑的事情:
- 你的线程有理由保持睡眠状态吗?
- 为什么不启动一个新线程,让它在完成工作后自然死亡呢?
- 如果在任何时间点只有一个代码路径处于活动状态(所有其他线程都处于休眠状态(,则您的设计不允许并发。
最后,如果您使用的是线程之间共享的变量,则应使用原子组学。这将确保对值的访问是同步的。
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 如果我们使用 notify_one() 来唤醒线程,我们还需要 yield() - C++?
- 唤醒多个线程以在每个条件下工作一次
- 视频在唤醒其他线程时输入设备断开连接
- 线程启动延迟 - 通知所有未唤醒所有线程
- 使用 Poco:Condition 唤醒两个线程
- std::condition_variable::notify_one() 不会唤醒等待线程
- 唤醒线程很耗时
- 如何定期唤醒 C++ 11 线程
- 我可以"force"线程唤醒吗?
- pthread_cond_wait唤醒多线程示例
- 如何唤醒从另一个线程选择没有超时时间的呼叫
- Boost::线程 / C++11 std::thread,想要唤醒工作线程的条件
- 固定到内核的 FIFO 线程上的 std::p romise::set_value 不会唤醒 std::future
- 线程同步和睡眠线程拒绝唤醒(LINUX)
- 在特定时间后唤醒线程
- 多线程同步和多线程唤醒
- 从另一个线程唤醒QThread::exec()
- std::condition_variable – 通知一次,但等待线程唤醒两次