惊群现象

什么是惊群

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

  1. 系统对用户进程/线程频繁的做无效的调度、上下文切换,系统性能大打折扣。
  2. 为了确保只有一个线程得到资源,用户必须对资源操作进行加锁保护,进一步加大了系统开销。

最常见的例子就是对于socket描述符的accept操作,当多个用户进程/线程监听在同一个端口上时,由于实际只可能accept一次,因此就会产生惊群现象。

Linux内核解决惊群问题的方法

在Linux 2.6版本之前,监听同一个socket的进程会挂在一个等待队列上,当请求到来时,会唤醒所有等待的子进程。
当时可以使用锁解决这种惊群问题。

for(;;) {
    lock();// 互斥锁
    int client = accept(...);
    unlock();
    if (client < 0) continue;
    ...
}

在Linux 2.6版本之后,通过引入一个标记位,解决掉了惊群问题。内核开发者增加了一个“互斥等待”选项。一个互斥等待的行为与睡眠基本类似,主要的不同点在于:
1)当一个进程加入等待队列时,如果该进程有 WQ_FLAG_EXCLUSEVE 标志置位,它被添加到等待队列的尾部。没有这个标志,则添加到队列开始。
2)当 wake_up 在一个等待队列上被调用时,它会唤醒第一个有 WQ_FLAG_EXCLUSIVE 标志的进程后停止。
也就是说,对于互斥等待的行为,比如对一个Socket,多线程阻塞accept时,系统内核只会唤醒所有正在等待此事件的队列的第一个,队列中的其他进程则继续等待下一次事件的发生,这样就避免的多个线程同时监听同一个socket时的惊群问题。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 《UNIX 网络编程卷一:套接字联网API》笔记 套接字 套接字编程接口,是在 TCP/IP 协议族中,应用层进入...
    超net阅读 11,117评论 2 13
  • 必备的理论基础 1.操作系统作用: 隐藏丑陋复杂的硬件接口,提供良好的抽象接口。 管理调度进程,并将多个进程对硬件...
    drfung阅读 8,929评论 0 5
  • 什么是惊群,这篇文章写的很好:举一个很简单的例子,当你往一群鸽子中间扔一块食物,虽然最终只有一个鸽子抢到食物,但所...
    舒小贱阅读 13,189评论 1 7
  • 操作系统概论 操作系统的概念 操作系统是指控制和管理计算机的软硬件资源,并合理的组织调度计算机的工作和资源的分配,...
    野狗子嗷嗷嗷阅读 14,174评论 3 34
  • 飞花逐旧梦 暑夜待凉风 白云依皓月 黑水伴墨城 远山牵行路 近宇藏途径 轻歌载思绪 尽处是归程
    涛涛不绝82阅读 1,241评论 0 3