多线程epoll服务器:唤醒睡眠在同一epollfd上的N个线程



我有一个多线程epoll服务器。我创建了一个epollfd,然后我将有X个线程处于休眠状态,用epoll_wait()等待SAMEepollfd中的任何事件。

现在我的问题是:当N>1&amp;N<十、

到目前为止,我一直使用Linux特定的eventfd功能,它只使用1个线程就可以很好地工作,但现在有多个线程在等待SAMEepoll-fd,出现了一个问题:

案例1)LT:如果我用"级别触发"模式添加我的eventfd,ALL线程将在我写入eventfd时唤醒,这就是级别触发模式的工作方式:一旦fd改变状态,让我们唤醒所有线程。

N=X

情况2)ET:如果我用"边缘触发"模式添加我的事件fd,当我向事件fd写入时,ONLY 1线程将唤醒,这就是边缘触发模式的工作方式:在我从read(eventfd, ...);接收EAGAIN之前,不再发生epollfd事件。

N=1

情况3)我也尝试过一个自管道技巧,向管道写N次会唤醒N个线程。相反,它不起作用:它不可靠,有时一个线程从管道中读取2个"令牌",有时读取1个或3个。

N=随机

在我尝试过的所有情况下,我都不能只得到N=N,我不能只唤醒N个线程,而是1或all或RANDOM。我错过了什么?有什么想法吗?注意:我还尝试了eventfd特定的EFD_SEMAPHORE标志,但没有任何帮助。

根据eventfd手册页面。


文件描述符是可读的(select(2)readfds论点如果计数器具有值大于0。

通过创建带有EFD_SEMAPHORE标志的事件fd:

(如果)eventfd计数器具有非零值,则read(2)返回包含值1的8个字节,并且计数器的值递减1。


使用信号量(EFD_SEMAPHORE标志)NONBLOCK(EFD_NONBLOCK标志)eventfd并等待电平触发的epoll()或正常的poll()

使用eventfd_write(fd, N)编写N线程你想醒来。

当线程唤醒时,执行read()。如果如果出现EAGAIN错误,您可以返回睡眠因为N已成功读取,并且因此N线程知道他们必须保持清醒。

缺点

所有线索都醒了(雷鸣般的群体问题)。

由于您主要要退出唤醒线程,正如您在评论中所澄清的,以下是您可以做的:

  • 使用ET和自管
  • 将数字N写入自管道(根据您的喜好,2或4字节int)
  • 在epoll_wait()上等待的线程将唤醒,从管道中读取数字N,如果它>1,则将其递减并写入自身管道,然后退出
  • 这会唤醒第二个线程,从管道中读取数字(现在为N-1)。如果它>1,则递减它并写入self-pipe并退出。…

  • 依此类推,在某个时刻,最后一个线程从管道中读取1。该线程应该退出,但不再写入管道。

相关内容

  • 没有找到相关文章

最新更新