Nio框架需要注意的两个问题(1)

研究了一段时间Nio框架,有Netty和Tomcat的Nio Connector总结了一些共性的问题的解决方案。

 

  1. Selector的register和select有锁冲突,例如tomcat的Nio Connector,他采用的Acceptor和Poller的模式,Acceptor只负责接收socket,Poller是负责读写的IO线程,这种模式不用于nginx,Poller(worker)既负责接收和读写的抢占式模块。这样Acceptor和Poller存在的一个交互就是register,Acceptor需要把接收到的socket注册给Poller。Poller实现了Selector执行select和并且遍历selectionKey操作的封装。

 


    假设Poller正在执行Selector的select方法并且同时Acceptor又接收了新的socket并执行register操作,这时候就会发生锁等待,集体参看http://xiaoz5919.iteye.com/blog/1518473。该如何解决这个问题呢。

    Tomcat是这样解决的,把注册当成一个event,当有注册发生时添加一个注册事件到队列中,Poller在每次执行select之前先处理注册事件队列。这样保证了register和select的执行顺序是永远是一致的,先执行register再执行select,有效地避免了锁冲突。

 


 

  再来看看代码,

 

 

   boolean hasEvents = events();//处理register和cancel事件


                    // Time to terminate?

                    if (close) {

                        timeout(0, false);

                        break;

                    }

                    try {

                        if ( !close ) {

                            if (wakeupCounter.getAndSet(-1) > 0) {

                                //if we are here, means we have other stuff to do

                                //do a non blocking select

                                keyCount = selector.selectNow();

                            } else {

                                keyCount = selector.select(selectorTimeout);

                            }

                            wakeupCounter.set(0);

                        }

 

再看一个细节问题,selector的wakeup是一个很昂贵的工作,假如有多个socket来register也只需一次wakeup,所以tomcat设置了wakeupCounter变量来操作唤醒次数并且只有wakeup==0时才执行一次唤醒操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值