主程序如何通过等待而不是加入同时等待多个线程?

Posted

技术标签:

【中文标题】主程序如何通过等待而不是加入同时等待多个线程?【英文标题】:How does a main program wait for several threads at the same time via wait rather than join? 【发布时间】:2021-07-18 12:37:07 【问题描述】:

我有一个主程序需要启动多个线程,这些线程会立即等待条件变量。然后主程序进入一个循环。主程序循环的每次迭代都会执行一个 notify_all 来唤醒所有线程。然后主程序等待所有线程完成它们的处理,然后开始主循环的下一次迭代。

我知道如何为一个线程执行此操作。我想我知道如何用多个线程来做到这一点,但是我对主程序应该如何等待所有线程有疑问。主程序不能使用 join 来完成,因为线程将等待主循环的下一次迭代而不是终止。所以主程序必须通过等待来完成。

每个线程当然会在返回等待之前立即通知主程序本次迭代已完成。我知道如何在主程序和一个线程之间来回通知和等待,并且我通常知道如何使用condition_variables。我知道如何避免丢失唤醒和虚假唤醒事件等。但是我对主程序应该如何等待所有线程通知,然后再继续循环的下一次迭代有点模糊。从概念上讲,主程序需要等待多个条件变量,每个线程一个。但这不是 condition_variables 的工作方式。您一次只能等待一个 condition_variable。

我可以想到两种方法来处理等待所有线程的主程序。我能想到的两种方法是,主程序将等待一个条件变量,所有线程在完成时都会通知该条件变量,或者主程序将等待多个条件变量,每个线程一个,主程序一次一个地等待它们。我确定我知道如何使后一种情况起作用。问题是前一种情况是否可行。如果它可以工作,我会想象一个不同的布尔变量,每个线程在完成迭代时会设置它。主程序的等待将有一个谓词依次测试每个布尔变量。等待处理将循环,直到它发现所有的布尔变量都打开了。这就是问题所在。我可以使用每个线程通知的一个 condition_variable 吗?还是我需要一个单独的条件变量来通知每个线程?

这对我的问题无关紧要,但是在循环的迭代 N 期间,每个线程正在完成的工作完全独立于当时其他线程正在完成的工作。但是在循环的第 N+1 次迭代期间,每个线程正在完成的工作取决于迭代 N 期间所有线程完成的工作。这就是为什么主程序必须等待所有线程在它之前完成迭代的原因可以通知任何线程开始下一次迭代。如果不是因为这个要求,我什至不需要 condition_variables。线程可以异步运行。主程序可以将它们全部启动并通过连接等待它们全部完成。

【问题讨论】:

【参考方案1】:

您可以使用需要互斥锁保护的计数器。在开始之前将其设置为0,每个线程在完成后都会增加它,因此您只需要一个对象来检查可以通过条件变量轻松完成的对象。

if (DoneCount == ThreadCount)
    // All threads done.

【讨论】:

【参考方案2】:

我可以使用每个线程通知的一个 condition_variable 吗?还是我需要一个单独的条件变量来通知每个线程?

任何一种方法都可以正常工作。只需等待每件事情以任何顺序连续发生,就可以完成等待所有一组事情的发生。您可以为每个事件使用共享条件变量或不同的条件变量。

【讨论】:

以上是关于主程序如何通过等待而不是加入同时等待多个线程?的主要内容,如果未能解决你的问题,请参考以下文章

多个 std::threads 和主程序执行出现问题

线程死锁

通过等待条件等待多个正在运行的线程

java多线程对CountDownLatch的使用实例

Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执行

java线程池5个线程同时运行 有一个线程等待数秒无法继续运行被结束掉,而其他4个线程不受那个线程的影响