我想我错过了一个关于多道程序设计的基本设计模式。我找到了一个问题的解决办法,但我认为它过于复杂。
在程序开始时,我会分配一个静态的工作线程池和一个主线程,它们在程序运行的整个过程中都存在。(下面的伪代码)
void *worker(){
while(1){
//perworker mutex lock
//wait for workerSIGNAL
//do calculations
//perworker mutex unlock
}
}
我的主线程向我的所有工作者发出信号,当工作者完成时,他们等待来自主线程的下一个信号。(下面的伪代码)
void *master(){
while(1){
//masterMutex lock
//wait for masterSignal
//signal all workerthread to start running
/*
SHOULD WAIT FOR ALL WORKER THREADS TO FINISH
(that is when workers are done with the calculations,
and are waiting for a new signal)
*/
//materMutex unlock
}
}
我的主线程从代码的另一部分(非线程)获得信号,这意味着只有一个主线程存在。(下面的伪代码)
double callMaster(){
//SIGNAL masterThread
//return value that is the result of the master thread
}
我的问题是,如何让主线程等待所有工人完成(等待下一个工人信号)?
我的解决方案非常复杂。我的workerthreads中有一个屏障,它等待所有工作线程完成,然后从我的一个线程(threadId=0)发出信号,在我的主线程底部等待一个workerOne条件。
它很好用,但并不漂亮,任何改进的想法都值得赞赏。
谢谢。
您是否考虑过使用pthread_join
http://kernel.org/doc/man-pages/online/pages/man3/pthread_join.3.html?这听起来像是在使用信号在线程之间进行通信。虽然这在某些情况下可能是合适的,但我认为在您的情况下,您可能会发现pthread_join的使用简化了代码。
我在下面概述了一些伪代码示例:
//this goes in your main thread
for (int i = 0; i < num_threads; ++i)
pthread_join(thread_id[i], ...
这样,主线程将阻塞,直到thread_id
数组中的所有线程,即工作线程终止。
您想要使用屏障。屏障用计数N
初始化,当任何线程调用pthread_barrier_wait
时,它会阻塞,直到总共有N
个线程处于pthread_barrier_wait
,然后它们都返回,屏障可以再次使用(具有相同的计数)。
有关详细信息,请参阅POSIX中的文档:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_wait.html
在Java中,您可以在此处使用初始值等于工作线程数的循环屏障。
对这个屏障的引用被传递给每个工作线程,这些线程在单个工作执行结束时调用barrier.await().
主程序将在barrier处await(),直到所有工作线程都到达执行点并调用barrier.await(.
只有当所有工作线程都调用了barrier.await()时,屏障才会被提升,main才能继续。
循环屏障类似于Latches,只是屏障是循环的,可以无限地重置。因此,在主循环的情况下,循环屏障是一个更好的选择。