需要对NIO底层源码有一定了解
概要: 在写Reactor模式多线程版版 出现了boos selector(就是处理channel连接的selector)往 worker selector 注册channel出现了阻塞问题(卡死不动了)。
问题就出现在断点处
MultiThreadEchoHandler 类会在boos selector接受到连接事件并接受之后初始化 然后把this 注册到worker selector中
boos selector接受到连接事件 往 worker selector中注册!!
源码解析:
seletor,channel,seletionKey 关系图
Channel.Rgister源码方法:
如关系图和源码所示 selector与channel 通过selectionKey双向绑定的!
Selector.Rgister源码方法:
如图所示 seletionKey以impl实例化封装channel与selector
在真正做注册动作之前需要获得keys set集合的对象锁
阻塞就产生在这里 一直被阻塞住 锁一直没被释放!!
那么我们的问题就出来了!!谁在boss selector 给worker selector注册channel时一直占这个锁
这里用jconsole 看看锁占用情况.
线程锁占用情况就可以看出 boss selector 往 worker selector注册时 锁一直就被worker自身占用着!
那么第二个问题就时worker什么方法会阻塞占锁
答案就是 select 调用的操作的系统的epoll
**select 会阻塞占锁 ,所以boss selector 往这个正在阻塞的selector 注册 会把boss selecor一直阻塞(-.- 有点绕) **
解决方案: 只要 boss selector 来注册了 就立即通知 worker selector立即放弃锁