在 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 中的事件通知文件描述符设置为边缘触发。
在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 acrossfork(2)
) are blocked inepoll_wait(2)
waiting on the same the sameepoll
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 fromepoll_wait(2)
. This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.
所以要获得这种单一唤醒行为,你必须在每个线程中调用 same epoll 描述符上的 epoll_wait()
,并且你必须注册你的epoll 中的事件通知文件描述符设置为边缘触发。