cmultithreadingsocketsepoll

How to process events detected by epoll as multithread?


We are implementing servers and clients using epoll and multithread

There are a total of 5 multithreads, and 100 clients will be connected.

The main thread wants to process the client's access request and make the thread work for each client's event.

The main thread adds accepted clients to epoll_fd.

In pthread_crate(...), we receive &epoll_fd as a factor, and the mulitithreads are doing epoll_wait().

However, if the current client requests connect(), other request from the server, All five multithreads detect events.

How can I prevent other threads from working for events that have already been processed?

Without using thread_poll.


Solution

  • In pthread_crate(...), we receive &epoll_fd as a factor, and the mulitithreads are doing epoll_wait(). However, if the current client requests connect(), other request from the server, All five multithreads detect events.

    This is called Thundering herd. And you should avoid it.

    In computer science, the thundering herd problem occurs when a large number of processes or threads waiting for an event are awoken when that event occurs, but only one process is able to handle the event. When the processes wake up, they will each try to handle the event, but only one will win. All processes will compete for resources, possibly freezing the computer, until the herd is calmed down again.

    To avoid this problem, you should ask main thread to call epoll_wait(). After main thread accept a new socket, it pass the socket to one of the worker thread.

    Moreover, thread pool is very important for server. By maintaining a pool of threads, the server increases performance and avoids latency in execution due to frequent creation and destruction of threads for short-lived tasks.

    Then you need a method to pass the newly accepted client to worker threads in the thread pool. It's called Producer–consumer problem. The main thread play as producer, the worker threads are consumers. The easiest way is to use a queue to decouple producer and consumers. The main thread pushes the accepted client to the head of the queue. And the worker threads pops client from the tail of the queue. Of course, you need to lock the queue while pushing/popping elements into/from the queue. And there are other ways to dispatch clients to workers, you can explore them by yourself.