Linux~惊群现象

惊群效应也叫做雷鸣群体效应。惊群现象就是多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终只有一个进程(线程)获得这个时间的“控制权”,对这个事件处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群。

为了更好的理解何为惊群,举一个很简单的例子,当你往一群鸽子中间扔一粒谷子,所有的各自都被惊动前来抢夺这粒食物,但是最终注定只可能有一个鸽子满意的抢到食物,没有抢到的鸽子只好回去继续睡觉,等待下一粒谷子的到来。这里鸽子表示进程(线程),那粒谷子就是等待处理的事件。

惊群现象会消耗这些:

(1)、系统对用户进程/线程频繁地做无效的调度,上下文切换系统性能大打折扣。

上下文切换过高会导致CPU像个搬运工,频繁地在寄存器和运行队列之间奔波,更多的时间花在了进程(线程)切换,而不是真正工作的进程(线程)上面。直接的消耗包括CPU寄存器要保存和加载(比如程序计数器)、系统调度器的代码需要执行。间接的消耗在于多核cache之间的数据共享。

(2)、为了确保只有一个线程得到资源,用户必须对资源操作进行加锁保护,进一步加大了系统开销。

通过锁机制解决惊群效应是一种方法,在任意时刻只让一个进程(线程)处理等待的事件。但是锁机制也会造成CPU等资源的消耗和性能损耗。目前一些常见的服务器软件是有的通过锁机制解决的,比如Nginx(它的锁机制是默认开启的,也可以关闭);还有些认为惊群对系统性能影响不大,没去做处理,比如Lighttpd。

accept()惊群:

主线程创建了socket、bind、listen之后,fork()出来多个进程,每个子进程都会开始循环处理(accept)这个listenfd。每个进程都阻塞在accept上,当有一个新的连接到来,所有的进程都会被唤醒,但是其中只有一个进程会接收成功,其余皆失败,重新休眠。

历史上,Linux的accept确实存在惊群问题,但现在的内核都解决该问题了。即,当多个进程/线程都阻塞在同一个socket的接收调用上时,当有一个新的连接到来,内核只会唤醒一个进程,其他进程保持休眠,根本不会被唤醒。

其实在Linux2.9版本以后,Linux内核已经解决了accept()函数的“惊群”现象,大概的处理方式就是,当内核接收到一个客户连接后,只会唤醒等待队列上的第一个进程(线程),所以如果服务器采用accept阻塞调用方式,在最新的Linux系统中已经没有“惊群效应”了

 

epoll惊群:
     
概述:
如果多个进程/线程阻塞在监听同一个监听socket fd的epoll_wait上,当有一个新的连接到来时,所有的进程都会被唤醒。
同样让我们假设一个场景:
主进程创建socket,bind,listen后,将该socket加入到epoll中,然后fork出多个子进程,每个进程都阻塞在epoll_wait上,如果有事件到来,则判断该事件是否是该socket上的事件如果是,说明有新的连接到来了,则进行接受操作。为了简化处理,忽略后续的读写以及对接受返回的新的套接字的处理,直接断开连接。
那么,当新的连接到来时,是否每个阻塞在epoll_wait上的进程都会被唤醒呢?
很多博客中提到,测试表明虽然epoll_wait不会像接受那样只唤醒一个进程/线程,但也不会把所有的进程/线程都唤醒。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值