当多个进程/线程同时等待同一个socket的事件,当事件发生时,多个进程/线程同时被唤醒,但只有一个进程/线程响应处理该事件,其余被唤醒的进程/线程从新休眠,这种状况称为惊群。linux
因为唤醒进程须要内核从新调度,因此那些没有响应处理事件的进程也被唤醒就意味着性能浪费,因此须要采起措施避免惊群发生。socket
须要说明的是,对于accept()函数,Linux2.6已经从内核层面解决了惊群问题,作法是当链接来到后,只唤醒等待队列中的第一个进程或线程。函数
当使用select,poll,epoll时,仍然会有惊群问题。性能
特别须要注意的是,即使是2.6之后的linux,epoll_wait在某些场景下不会出现惊群问题,但其仍旧有很大可能会在另外的场景中出现惊群问题。线程
例如,当epoll_wait以后又sleep的状况,由于信号将唤醒sleep,再也不是内核唤醒等待队列中的第一个进程。server
(1)在accept以前加锁,像Nginx那样;
lock;
accept();
unlock;队列
(2)在linux kernel 3.9以后利用SO_REUSEPORT,将socket属性加多一个SO_REUSEPORT
fcntl(serverFd,F_SETFL,flags | O_NONBLOCK |SO_REUSEPORT)进程