我如何等待任何/所有 pthread 完成?
我只希望我的主线程在退出之前等待所有(p)线程完成。
由于不同的原因,这些线程经常出现和消失,我真的不想跟踪所有的线程 - 我只想知道它们什么时候全部消失。
wait() 对子进程执行此操作,当没有子进程时返回 ECHILD,但是 wait 不适用于 (p) 线程。
我真的不想经历保留每个未完成线程的列表(当它们来来去去时)的麻烦,然后必须对每个线程调用 pthread_join 。
有没有一种快速而肮脏的方法可以做到这一点?
I just want my main thread to wait for any and all my (p)threads to complete before exiting.
The threads come and go a lot for different reasons, and I really don't want to keep track of all of them - I just want to know when they're all gone.
wait() does this for child processes, returning ECHILD when there are no children left, however wait does not (appear to work with) (p)threads.
I really don't want to go through the trouble of keeping a list of every single outstanding thread (as they come and go), then having to call pthread_join on each.
As there a quick-and-dirty way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您是否希望主线程在所有线程完成后执行任何特定操作?
如果没有,您可以让主线程简单地调用
pthread_exit()
而不是返回(或调用exit()
)。如果
main()
返回,它会隐式调用(或表现得如同调用)exit()
,这将终止进程。但是,如果main()
调用pthread_exit()
而不是返回,则不会发生对exit()
的隐式调用,并且进程会获胜不会立即结束 - 当所有线程终止时它将结束。不能太快而脏。
这是一个小示例程序,可以让您看到其中的差异。将
-DUSE_PTHREAD_EXIT
传递给编译器以查看进程等待所有线程完成的情况。在没有定义该宏的情况下进行编译,以查看进程停止线程的情况。Do you want your main thread to do anything in particular after all the threads have completed?
If not, you can have your main thread simply call
pthread_exit()
instead of returning (or callingexit()
).If
main()
returns it implicitly calls (or behaves as if it called)exit()
, which will terminate the process. However, ifmain()
callspthread_exit()
instead of returning, that implicit call toexit()
doesn't occur and the process won't immediately end - it'll end when all threads have terminated.Can't get too much quick-n-dirtier.
Here's a small example program that will let you see the difference. Pass
-DUSE_PTHREAD_EXIT
to the compiler to see the process wait for all threads to finish. Compile without that macro defined to see the process stop threads in their tracks.正确的方法是跟踪所有的 pthread_id,但是您要求一种快速而肮脏的方法,所以就在这里。基本上:
。。
The proper way is to keep track of all of your pthread_id's, but you asked for a quick and dirty way so here it is. Basically:
.
如果您不想跟踪线程,那么您可以分离线程,这样您就不必关心它们,但为了知道它们何时完成,您将不得不走得更远。
一个技巧是保留线程状态的列表(链表、数组等)。当线程启动时,它会将其在数组中的状态设置为类似 THREAD_STATUS_RUNNING 的值,并在结束之前将其状态更新为类似 THREAD_STATUS_STOPPED 的值。然后,当您想检查所有线程是否已停止时,您可以迭代该数组并检查所有状态。
但请不要忘记,如果您执行类似的操作,则需要控制对数组的访问,以便一次只有一个线程可以访问(读取和写入)它,因此您将需要对其使用互斥体。
If you don't want to keep track of your threads then you can detach the threads so you don't have to care about them, but in order to tell when they are finished you will have to go a bit further.
One trick would be to keep a list (linked list, array, whatever) of the threads' statuses. When a thread starts it sets its status in the array to something like THREAD_STATUS_RUNNING and just before it ends it updates its status to something like THREAD_STATUS_STOPPED. Then when you want to check if all threads have stopped you can just iterate over this array and check all the statuses.
Don't forget though that if you do something like this, you will need to control access to the array so that only one thread can access (read and write) it at a time, so you'll need to use a mutex on it.
你可以保留所有线程ID的列表,然后对每个线程执行pthread_join,?
当然,您需要一个互斥锁来控制对线程 ID 列表的访问。你会
还需要某种可以在迭代时修改的列表,也许是 std::set
you could keep a list all your thread ids and then do pthread_join on each one,
of course you will need a mutex to control access to the thread id list. you will
also need some kind of list that can be modified while being iterated on, maybe a std::set<pthread_t>?
感谢大家的精彩回答!关于使用内存屏障等已经有很多讨论 - 所以我想我应该发布一个答案来正确地显示它们用于此目的。
请注意,__sync 宏是“非标准”GCC 内部宏。 LLVM 也支持这些 - 但如果您使用其他编译器,您可能需要做一些不同的事情。
另一个需要注意的重要事项是:当您可以轻松地将其投入工作时,为什么要烧毁整个核心,或者在紧密的轮询循环中浪费“一半”的 CPU 旋转来等待其他人完成?以下 mod 使用初始线程运行其中一个工作线程,然后等待其他线程完成:
请注意,我们从“1”而不是“0”开始创建线程,然后直接内联运行“线程 0”,等待让所有线程在完成后完成。我们将 &thread[0] 传递给它以保持一致性(即使它在这里毫无意义),尽管实际上您可能会传递您自己的变量/上下文。
Thanks all for the great answers! There has been a lot of talk about using memory barriers etc - so I figured I'd post an answer that properly showed them used for this.
Note that the __sync macros are "non-standard" GCC internal macros. LLVM supports these too - but if your using another compiler, you may have to do something different.
Another big thing to note is: Why would you burn an entire core, or waste "half" of a CPU spinning in a tight poll-loop just waiting for others to finish - when you could easily put it to work? The following mod uses the initial thread to run one of the workers, then wait for the others to complete:
Note that we start creating the threads starting at "1" instead of "0", then directly run "thread 0" inline, waiting for all threads to complete after it's done. We pass &thread[0] to it for consistency (even though it's meaningless here), though in reality you'd probably pass your own variables/context.