Biny

什么是惊群效应,如何有效避免惊群效应?

Biny 2016-11-25 22:59:39    201241 次浏览

惊群效应就是当一个fd的事件被触发时,所有等待这个fd的线程或进程都被唤醒。

一般都是socket的accept()会导致惊群(当然也可以弄成一堆线程/进程阻塞read一个fd,但这样写应该没什么意义吧),很多个进程都block在server socket的accept(),一但有客户端进来,所有进程的accept()都会返回,但是只有一个进程会读到数据,就是惊群。实际上现在的Linux内核实现中不会出现惊群了,只会有一个进程被唤醒(Linux2.6内核)。

使用mutex锁住多个线程是不会惊群的,在某个线程解锁后,只会有一个线程会获得锁,其它的继续等待。

举一个很简单的例子,当你往一群鸽子中间扔一块食物,虽然最终只有一个鸽子抢到食物,但所有鸽子都会被惊动来争夺,没有抢到食物的鸽子只好回去继续睡觉, 等待下一块食物到来。这样,每扔一块食物,都会惊动所有的鸽子,即为惊群。对于操作系统来说,多个进程/线程在等待同一资源是,也会产生类似的效果,其结 果就是每当资源可用,所有的进程/线程都来竞争资源,造成的后果:

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

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

最常见的例子就是对于socket描述符的accept操作,当多个用户进程/线程监听在同一个端口上时,由于实际只可能accept一次,因此就会产生惊群现象,当然前面已经说过了,这个问题是一个古老的问题,但目前的内核版本已经修复了这个问题,一个链接过来,内核只会唤醒一个子进程出来accept,这样就不用担心惊群效应了。
内容加载中