我需要知道是否有一种方法可以将等待条件变量的线程“排队”,以便它们以正确的顺序被唤醒……也就是说,无需编写一堆排队代码。
在大多数系统中,以下生产者/消费者模型的反转(在满邮箱时阻塞)可能无法确保排序:
unique_lock lock1(mutex), lock2(mutex)
ConditionVariable cv
代码块A:(多线程调用)
lock(lock1)
timestampOnEntry = now()
cv.wait(lock1) // Don't worry about spurious notifies, out of scope.
somethingRequiringMonotonicOrderOfTimestamps(timestampOnEntry)
unlock(lock1)
代码块 B:(由单个线程调用,通常在循环中)
lock(lock2)
somethingVeryVerySlow()
(1) unlock(lock2) // the ordering here is not a mistake
(2) cv.notify_one(lock2) // prevents needless reblocking in code block A
请注意第 (1) 和 (2) 行的顺序。如果通知线程在 代码块 B 中的线程解锁之前唤醒,这可以防止在代码块 A 中出现不必要的第二个守卫 block 。
问题是,如果多个线程在 wait 时被“阻塞”,我需要知道是否 *notify_one* 将按照阻塞的顺序唤醒它们。可能不是(如在 Java 中)。如果不是默认情况下,如果有办法指定的话。
这当然可以通过一堆排队代码来完成,但我更愿意使用预先 jar 装的 BOOST 方法,无论 jar 装的内容有多复杂。当然,如果我将 *cv.notify_one(guard)* 转换为 *cv.notify_all(guard)*,无论如何我都需要执行排队代码。
最佳答案
标准没有给出这样的保证,notify_one
可能会唤醒当前正在等待的任何线程(§30.5.1):
void notify_one() noexcept;
Effects: If any threads are blocked waiting for*this
, unblocks one of those theads.
确保特定线程对事件使用react的唯一方法是唤醒所有 线程,然后使用一些额外的同步机制将除正确线程之外的所有线程送回 sleep 状态。
由于平台必须满足的要求,这是一个基本限制:通常条件变量的实现方式是将等待线程置于挂起状态,并且在发生通知之前不会再次被系统调度.不需要调度程序实现来提供选择特定线程进行唤醒的功能(实际上很多都不需要)。
因此这部分逻辑不可避免地必须由用户代码处理,这反过来意味着您必须唤醒所有线程以使其工作,因为这是确保正确线程被唤醒的唯一方法全部。
关于C++/BOOST:condition_variable::wait( )/notify( ) 是否确保线程等待的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19829754/