【发布时间】:2022-01-23 07:38:39
【问题描述】:
我在cppreference 上找到的信息在这方面含糊不清,所以我在这里问。假设我有两个线程在等待一个条件,一个具有真谓词,另一个是假的(例如condition.wait(lock, [=]{ return some_condition; })。主线程决定用cond.notify_one()随机通知其中一个。
假设选择的等待线程是谓词为假的线程。线程是否会隐式通知下一个(如果有剩余),还是注定要等到虚假唤醒?
如果只有一个线程被唤醒,无论其条件是成功还是失败,第一个线程尝试唤醒下一个线程以保证成功通知的好方法是什么?一个天真的修复:
condition.wait(lock, [=] {
if (!some_condition) condition.notify_one();
return some_condition;
});
除了悲观之外,“通知波”可能会重复通知相同的线程,这是无效的 + 永远不会停止,以防没有线程有成功的谓词。 notify_all() 是行不通的,因为我们可能会意外地唤醒多个满足条件的线程,同时我们最多只希望一个线程通过。
【问题讨论】:
-
不保证通知哪个线程,无论哪个线程正在执行通知。可以说,如果两个线程都收到同一个 cv 的通知,但两者或其中一个都可以做有用的工作,那么两个线程都应该被通知(通知所有)。我通常为每个条件变量争取一个“条件”。推理起来更容易。
-
"主线程决定用 cond.notify_one() 随机通知其中一个。" 如果多个线程等待一个条件,则不应使用 @ 987654326@.
-
@NicolBolas 有多个等待,但我希望一次只唤醒一个,这将在其锁定期间使所有其他等待线程的谓词为假,并且然后在关键部分的末尾再次使某些线程成为真的。我会使用信号量,但只有特定类型的线程可以在任何给定时间访问临界区。
-
@MarkedasDuplicate: "这将在其锁定期间使所有其他等待线程的谓词为假,然后在结束时再次使某些线程为真临界区。”这就是所谓的“锁定互斥体”。您根本不需要更改条件即可执行此操作。
-
@MarkedasDuplicate:在我看来,这一切听起来就像您需要一个任务调度系统,而不是条件变量。您可以根据任务是在组 n 还是组 m 中来排序要执行的任务。
标签: c++ concurrency synchronization c++20 condition-variable