我正在实现ChannelInboundHandlerAdapter,并且对并发性有疑问。是否有必要使其线程安全?我的意思是我必须为每个客户端的 session 存储一些状态。

public class Impl extends ChannelInboundHandlerAdapter{
    private List<Integer> someState;
    //

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        int size = someState.size();  //Should I worry about memory consitency here?
        //...
    }
}

事情是,如果从一个请求到另一个请求channelRead方法被不同的线程调用,那么我将不得不放置一些内存障碍。

有必要吗?还是Netty自己照顾它?

最佳答案

对于Netty 4.x

Well-defined thread model

尽管尝试修复3.5中的不一致问题,但3.x中没有明确定义的线程模型。 4.0定义了一个严格的线程模型,可以帮助用户编写ChannelHandler而不用过多担心线程安全性。

除非使用@Sharable注释ChannelHandler,否则Netty永远不会同时调用ChannelHandler的方法。 这与处理程序方法的类型无关-入站,出站或生命周期事件处理程序方法。

  • 用户不再需要同步入站或出站事件处理程序方法。
  • 4.0不允许多次添加ChannelHandler,除非使用@Sharable注释。
  • Netty进行的每个ChannelHandler方法调用之间总是存在事前发生的关系。
  • 用户不需要定义volatile字段即可保留处理程序的状态。
  • 用户在向ChannelPipeline添加处理程序时可以指定EventExecutor。
  • 如果指定,则始终由指定的EventExecutor调用ChannelHandler的处理程序方法。
  • 如果未指定,则处理程序方法始终由与其关联的Channel注册到的EventLoop调用。
  • 分配给处理程序或 channel 的
  • EventExecutor和EventLoop始终是单线程的。
  • 处理程序方法将始终由同一线程调用。
  • 如果指定了多线程EventExecutor或EventLoop,则将首先选择一个线程,然后将使用选定的线程,直到注销为止。
  • 如果在同一管道中的两个处理程序被分配了不同的EventExecutor,则它们将同时被调用。如果多个处理程序访问共享数据,即使共享数据仅由同一管道中的处理程序访问,用户也必须注意线程安全。
  • 添加到ChannelFuture的ChannelFutureListener始终由分配给将来的关联Channel的EventLoop线程调用。
  • ChannelHandlerInvoker可用于控制Channel事件的顺序。 DefaultChannelHandlerInvoker将立即执行EventLoop线程中的事件,并将其他线程中的事件作为EventExecutor上的Runnable对象执行。请参阅以下示例,以了解与EventLoop线程和其他线程中的Channel进行交互时可能产生的含义。

  • (强调是我的)

    10-08 16:08