在 Linux 中等待多线程事件的最佳实践(如 WaitForMultipleObjects)

Best practice for waiting for events on multiple threads in Linux (like WaitForMultipleObjects)

在Windows中有API WaitForMultipleObjects,如果在多个线程中注册了一个事件,则在该事件发生时只唤醒一个线程。我现在必须移植一个在其线程池中使用它的应用程序,我正在寻找在 Linux.

中执行此操作的最佳实践

我知道 epoll 可以等待 fds(我可以用 pipe 创建它),但是在多个线程中等待一个 FD 可能会唤醒每个线程 on event 当只有一个是需要。

在 Linux 上实施此行为的最佳做法是什么?我真的不想将一个事件拆分为具有与工作线程一样多的 FD,因为这可能会在某些系统上达到 FD 限制,因为我有很多事件(所有事件都会被拆分)。

我想的是创建 1 个主线程,将工作委托给可用的工作人员(或者如果所有工作人员都在工作,则将任务排队),但这意味着我有一个额外的上下文切换(因此放弃计算时间)因为主人会醒来,然后唤醒另一个工人。如果没有其他可能干净地实现它,我会这样做。不幸的是,我无法摆脱当前的架构,所以我需要解决这个问题。

是否有任何API适用于此类问题?

epoll() 是正确的解决方案,尽管您可以考虑使用 eventfd() 文件描述符而不是 pipe() 文件描述符来发送事件信号。从 epoll(7) man page 中查看此文本:

If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.

所以要获得这种单一唤醒行为,你必须在每个线程中调用 same epoll 描述符上的 epoll_wait(),并且你必须注册你的epoll 中的事件通知文件描述符设置为边缘触发。