假设我有一堆工作线程在等待,直到队列中有任务。
通常,您让生产者调用生产函数,然后notify_one
工作线程就可以解除阻塞并继续。
但是,假设当生产者生产时,没有线程在等待condition_variable
。生产者将通知,这将不执行任何操作。然后消费者到达和condition_variable
,wait
但它错过了之前的通知。
现在您在队列中有一个任务,直到生产者再次调用通知,此时队列中将有两个任务。
我的问题是,当有可用线程时,如何防止队列中有作业在等待?
例子:
struct ThreadPool
{
static inline std::mutex mutex;
static inline std::condition_variable condition_var;
static inline int number_of_things_to_consume = 0;
static void consume()
{
std::unique_lock lock{ mutex };
/* THE WORKER THREAD COULD BE WAITING HERE WITH SOMETHING IN THE QUEUE
- BECAUSE THE PRODUCER CALLED NOTIFY ONE BUT NO THREAD WAS WAITING YET */
condition_var.wait(lock, []() {return number_of_things_to_consume > 0; });
/* CONSUME */
}
static void produce()
{
std::unique_lock lock{ mutex };
++number_of_things_to_consume;
condition_var.notify_one();
}
};
底线:
由于您使用了
wait
带有谓词的a,因此您的担心是没有根据的。您的代码没有问题,不会出现这种情况。
更多信息:
正如您在文档中看到的,使用
wait
谓词(如您所做的那样)相当于:因此,如果谓词为真(因为生产者添加了作业),消费者将根本不会等待。
而且由于生产者始终在锁定的情况下更新谓词(确实应该如此),因此消费者在陷入困境时不会错过它
wait
。附注:为了处理虚假唤醒,
还建议 使用谓词而不是裸谓词。因此,一般建议始终使用谓词。
wait
wait