今天聊的也是一个老生常谈的问题了:JDK Selector 的空轮询 bug。
今天来简单地扒一下,这玩意大概能追溯到 06 年,并且基于这个 BUG 我们再发散下,看看能给我们什么启发。
追溯
最近我不是一直在写 Netty 系列嘛,我想谈到什么 Netty ,但凡你在网上看过相关资料,那肯定会提到 JDK NIO 在 Linux 系统下空轮询的 bug,就是调用 Selector.select(timeout),即使没事件发生,也不会阻塞 timeout 时间,而是立马 return,这样的空轮询导致 CPU 100%。
产生这个 bug 大致的原因我讲下:连接突然中断,poll 和 epoll 会被 POLLHUP 或者 POLLERR 事件唤醒,于是 Selector 虽然被唤醒了,但是 JDK Selector 一看,没事件(JDK只定义了CONNECT、READ、WRITE、ACCEPT这几个事件)需要处理啊?
然后就又循环了....没事件要处理啊,然后就又循环了....没事件要处理啊,然后就又循环了....
如此往复,空轮询使得 CPU 100%。
这个 BUG 真算是个老黄历了,我查了查 JDK 的 bug 库,大致 13 年 3 月份之后就没提相关的 bug ,而且按照官方的说法这也和 Linux 版本有关,至今应该没这问题了?(我不确定)。
我们来回顾一下 bug 库的历史。
我查了下最早提到的 Selector(底层用的是 poll 或者 epoll) 在 Linux 不会阻塞的 BUG 是在 06 年 3 月 24 日。