如果我们使用关闭通道的hashwheel计时器,我们是否需要以close方法进行同步

时间:2013-12-07 18:05:27

标签: java synchronization netty

如果我们使用关闭通道的hashwheel计时器

,我们是否需要以close方法进行同步

我有一个处理程序,它被添加到管道行中以及传递给处理程序的散列轮式计时器,为来自client.Timer的每个新连接创建处理程序在管道工厂中创建。我需要的是如果客户端在指定的时间内没有进行任何活动,则计时器应关闭该通道。并且在处理程序中我有close方法,当关闭事件被触发时,它会被提供。所以是否需要在close方法上进行同步...因为当调用close时,将调用所有回调处理程序...它是否会导致死锁....

请建议

2 个答案:

答案 0 :(得分:0)

答案取决于很多事情 - 因此要求查看您的代码。

HashedWheelTimer始终在使用默认Java线程工厂或提供的线程工厂创建的后台线程上触发超时事件。除非您正在采取特定操作来控制它,否则如果您的TimerTask由HashedWheelTimer直接执行,则很可能是在一个单独的线程上,您应该执行任何必要的同步。

如果您使用的是Netty的ReadTimeoutHandler或IdleStateHandler,则行为取决于您使用的Netty版本。在Netty 3.5之前,在HashedWheelTimer线程上触发了超时,并且可能需要进行同步。

由于Netty 3.5(包括Netty 4.0),超时处理程序将超时事件排队到分配了通道的I / O工作线程。这意味着事件将与所有其他频道事件一起串行引发。不需要同步。

如果您使用的是Netty 3.5或更高版本,我建议您考虑使用提供的超时处理程序,因为它们非常易于使用。如果使用其中一个提供的处理程序不是一个选项,您可以自己将事件排队到I / O工作程序。你如何实现这一点取决于Netty版本,所以我建议查看ReadTimeoutHandler的源代码,看看它是如何完成的。

请注意,上面假设您没有向管道添加执行程序但不保留通道事件的顺序(例如,Netty 3.x中的MemoryAwareThreadPoolExecutor)。

答案 1 :(得分:0)

class DataStreamHandler extends IdleStateAwareChannelUpstreamHandler {
private final Timer timer;
private final Timer idleTimer;`enter code here`
private Channel channel;
private SslHandler sslhandler;
private String serverId;
private boolean certClientId = false;
public enum State {
 Open{ 
 protected boolean handle (DataStreamHandler dh, Message event) {
 //some logic to proceed to Established state handler
 //other wise closed state handler
  handler.write(event.getMessage(),),
                    State, null, true);
                    // write methods sets the state specified
} 
},
 Established{ protected boolean handle (DataStreamHandler dh, Message event) {
 //some logic some logic to proceed to Bind state handler
  handler.write(event.getMessage(),),
                    State, null, true);
                    // write methods sets the state specified other wise closed state handler
}  },
 Bind { protected boolean handle (DataStreamHandler dh, Message event) {
// some logic values below are configurable
channelPipeline.replace(idlestatehandler, new IdleStateHandler(this.idletimer, 10000,0,10000, milliseconds));
 handler.write(event.getMessage(),),              State, null, true);// write methods sets the state specified
}                   
} 
},
 Closed{ protected boolean handle (DataStreamHandler dh, Message event) {
//logic to set handler to fire closed event
} }
};
@Override
public void  channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) {
synchronized(this) {
this.channel = ctx.getChannel();
this.sslHandler= ctx.getPipeline().get(SslHandler.class);
//set enum state to Established
}
super.channelConnected(ctx, e);     
}
@Override
public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) {
synchronized(this) {            
if (!this.setCertClientId && !setCertClientId()) {
return;
}
//before processing the message ssl handler is used
}
}
  private boolean setCertClientId() {
synchronized(this) {
this.setCertClientId = true;
if (this.sslHandler == null) {
return true;
}
//the ssl handler is added for every channel in getpipeline.
final SSLEngine sslEngine = sslHandler.getEngine(); 
//ssl related checks done other wise channel close is called
}
}
@Override
public void channelClosed(final ChannelHandlerContext ctx,
final ChannelStateEvent e)throws Exception { //NOSONAR, throw exception is from netty
synchronized(this) {
//set enum state to CLOSED
}
super.channelClosed(ctx, e);
}   
private void closeChannel() {
final SslHandler theSslHandler;
synchronized(this) { 
this.closePending = true;
theSslHandler =  this.sslHandler;
if (sslHandler == null) {
future = getChannel().close();
} else  {
future = theSslHandler.close();
}
  monitorCloseChannel(future);   // this methd has a listener to future 
  if(theSslHandler != null) {
    // the CloseTask is  a static class which impelemets the timer task to close the stream or the channel depending upon boolean value supplied
       this.timer.newTimeout(new CloseTask(this, true), this.closeTimeoutMs, TimeUnit.MILLISECONDS);
       }
}
    super.channelClosed(ctx, e);
    }               

  @Override
    public void channelIdle(final ChannelHandlerContext ctx, 
                            final IdleStateEvent e) throws Exception { //NOSONAR, throw exception is from netty
    synchronized(this) {
      switch (e.getState()) {
        case ALL_IDLE:
          if (this.closePending) { 
                   // close the channel directly
          } else { 
              this.closePending = true;
              //call the CloseTask class to close the channel or stream
          }
          break;
            case READER_IDLE:
                if (getState() == State.ESTABLISHED) {
                 //some logic
                }
          break;
         case WRITER_IDLE:

          break;
          }
         }
    super.channelIdle(ctx, e);
}               

 @Override
    public void exceptionCaught(final ChannelHandlerContext ctx, 
                                             final ExceptionEvent e)
            throws Exception {    
     if (!this.closePending) {

        if (//checked for various exceptions) {
          //call
        closeChannel();
        } else {

         // call the CloseTask timertask class to close the channel or stream
                }
         } else {

                log.debug("Received exception while closing", e.getCause());
}
} 
}       
protected abstract boolean handle (DataStreamHandler dh, Message event);
public DataStreamHandler () {
this.timer = timer;
this.idleTimer= idleTimer;
this.channel= channel;
this.sslhandler=sslhandler;
this.serverId=serverId;
}
}