假设我有两组线程。一个组的功能是向数组添加元素,另一个组的功能是在数组包含相同元素时从数组中删除元素。规则是线程无法从数组中删除元素,如果它是空的并且必须等待。监视器用于解决此同步问题。
考虑一个场景,其中所有线程同时启动,消费者线程首先锁定互斥锁,然后检查阵列是否为空,条件为假,因此它解锁互斥锁。然后生产者线程首先锁定互斥锁,添加元素并通知所有等待的线程并解锁互斥锁。问题是,等待线程是否在通知后首先获得对互斥锁的访问,并且等待线程可以尝试删除该元素,或者互斥锁再次空闲,并且任何线程都可以再次锁定它并且等待线程不是在条件失败后完成,但让我们说它被放回到线程池中。
答案 0 :(得分:2)
首先,让我们明确一些事情(包含cppreference's page about std::condition_variable
的精髓):
<强>消费者强>
wait
上的消费者std::condition_variable
使用以下步骤:
std::unique_lock<std::mutex>
<强>生产者强>
生产者notify
遵循以下步骤std::condition_variable
- s:
notify_one
执行notify_all
或std::condition_variable
(不需要保留锁定通知)<强>答案强>
等待线程在收到通知后会先获取对互斥锁的访问权限,等待的线程可以尝试删除该元素
是的,可能有多个消费者处于相同的状态,并且每个消费者都可能消耗单个对象,这就是为什么每个等待的线程都应该使用额外的逻辑条件来防止虚假唤醒(参见粗体消费者部分的文字)。 wait
的{{1}}方法甚至有一个特定的原型,已包含它:
std::condition_variable
当消费者醒来时,它已经获得了锁定!因此,如果满足条件(例如template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
),则可以安全地使用。