當多個進程/線程同時等待同一個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)進程