对于条件变量,假设有一些相关的“条件”(在您的情况下是数据行)需要专门检查和更新(因此是互斥锁)。无论您选择哪种其他机制,您都需要弄清楚如何确保对“工作队列”的独占访问(无论是单个插槽还是真正的队列)。
使用共享队列,数据结构将始终有 2 个写入者(主线程 + 预期工作线程)和 N-1 个读取者。您可以使用读写锁 (rwlock) 来确保完整性。
或者,您可以有 N 个单独的队列(每个工作人员一个)。您会将数据行的副本推送给每个工作人员。
至于一次唤醒多个线程:您可以让您的工作人员“休眠”(例如使用 select())并使用 pthread_signal()(在循环中)唤醒它们。
您也可以使用pthread_barrier_wait()。
pthread_barrier_wait() 函数应在屏障引用的屏障处同步参与线程。调用线程应阻塞,直到所需数量的线程调用了指定屏障的 pthread_barrier_wait()。
当所需数量的线程调用了指定屏障的 pthread_barrier_wait() 时,常量 PTHREAD_BARRIER_SERIAL_THREAD 应返回给一个未指定的线程,并且零应返回给每个剩余线程。此时,屏障应重置为最近引用它的 pthread_barrier_init() 函数的结果。
- 使用pthread_barrier_init()初始化屏障(count = 1 + # of workers)
- 在每个worker中,循环调用pthread_barrier_wait();当它返回时,新数据已准备好
- 在主线程中,调用 pthread_barrier_wait() 向工作人员发出信号
不幸的是(正如 OP 所指出的),在下一次迭代中,在先前激活的工作人员完成其工作之前,不会唤醒任何工作人员。
一个更简单的架构将使主线程将事件分派给适当的工作人员(而不是唤醒所有工作人员并让他们弄清楚哪个是预期的接收者)。除非您拥有与 worker 一样多的核心,否则测试无论如何都不会真正并行发生。此外,即使您有足够的核心让工作人员并行运行,其中 N-1 也不会在完成测试之前得知“获胜者”已接手工作,因此所有核心的总工作量更高.