簡體   English   中英

多線程epoll服務器:喚醒在同一epoll fd上休眠的N個線程

[英]multithreaded epoll server: wake up N threads sleeping on the same epoll fd

我有一個多線程epoll服務器。 我創建了一個epoll fd,然后我將讓X個線程epoll_wait()休眠狀態,並使用epoll_wait()等待來自該SAME epoll fd的任何事件。

現在我的問題是:如何喚醒N> 1 && N <X的N個線程?

到現在為止,我一直使用Linux特定的eventfd工具,並且僅使用1個線程就可以很好地工作,但是現在有多個線程在等待SAME epoll fd時出現了問題:

情況1)LT:如果我將我的eventfd添加為“級別觸發”模式,則當我寫入eventfd時, 所有線程都將喚醒,這就是級別觸發模式的工作方式:一旦fd更改狀態,就喚醒所有線程。

N = X

情況2)ET:如果我以“邊緣觸發”模式添加eventfd,則在寫入eventfd時喚醒1個線程,這就是邊緣觸發模式的工作方式:在收到來自EAGAIN之前不再有epollfd事件read(eventfd, ...);

N = 1

情況3)我也嘗試過使用自管道技巧,向該管道寫入N次將喚醒N個線程。 相反,它不起作用:它不可靠,有時一個線程從管道中讀取2個“令牌”,有時為1或3。

N =隨機

在所有嘗試的情況下,我無法僅獲得N = N,我無法僅喚醒N個線程,而不能喚醒1個或ALL或RANDOM。 我想念什么? 有什么想法嗎? 注意:我也嘗試了eventfd專用的EFD_SEMAPHORE標志,而沒有任何幫助。

根據eventfd手冊頁。


如果計數器的值大於0,則文件描述符是可讀的(select(2)readfds參數; poll(2)POLLIN標志)。

通過使用EFD_SEMAPHORE標志創建一個eventfd:

(如果)eventfd計數器的值非零,則read(2)返回8個字節,其中包含值1,並且該計數器的值減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,則將其遞減並寫入自管道並退出。 ...

  • 以此類推,最后一個線程從管道讀取1。 該線程應退出,但不再寫入管道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM