Netty 中的并发
Concurrency in Netty
我正在实施 ChannelInboundHandlerAdapter
并且对并发性有疑问。是否有必要使其成为线程安全的?我的意思是我必须为每个客户的每个会话存储一些状态。
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
3.x 中没有明确定义的线程模型,尽管在 3.5 中尝试修复它的不一致性。 4.0 定义了严格的线程模型,帮助用户编写 ChannelHandler 而无需过多担心线程安全。
- Netty 永远不会并发调用 ChannelHandler 的方法,除非 ChannelHandler 使用 @Sharable 注释。 这与处理程序方法的类型无关 - 入站、出站或生命周期事件处理方法。
- 用户不再需要同步入站或出站事件处理程序方法。
- 4.0 不允许多次添加 ChannelHandler,除非使用 @Sharable 注释。
- Netty 的每个 ChannelHandler 方法调用之间始终存在先行关系。
- 用户不需要定义可变字段来保持处理程序的状态。
- 用户可以在向 ChannelPipeline 添加处理程序时指定 EventExecutor。
- 如果指定,ChannelHandler 的处理程序方法始终由指定的 EventExecutor 调用。
- 如果未指定,则处理程序方法始终由其关联的 Channel 注册到的 EventLoop 调用。
- 分配给处理程序或通道的 EventExecutor 和 EventLoop 始终是单线程的。
- 处理程序方法将始终由同一线程调用。
- 如果指定多线程EventExecutor或EventLoop,将首先选择其中一个线程,然后使用所选线程直到注销。
- 如果同一管道中的两个处理程序分配有不同的 EventExecutors,则它们会同时被调用。如果多个处理程序访问共享数据,即使共享数据仅由同一管道中的处理程序访问,用户也必须注意线程安全。
- 添加到 ChannelFuture 的 ChannelFutureListeners 始终由分配给未来关联 Channel 的 EventLoop 线程调用。
- ChannelHandlerInvoker 可用于控制 Channel 事件的顺序。 DefaultChannelHandlerInvoker 立即执行来自 EventLoop 线程的事件,并将来自其他线程的事件作为 EventExecutor 上的 Runnable 对象执行。请参阅以下示例,了解在与来自 EventLoop 线程和其他线程的 Channel 交互时可能产生的影响。
(强调是我的)
我正在实施 ChannelInboundHandlerAdapter
并且对并发性有疑问。是否有必要使其成为线程安全的?我的意思是我必须为每个客户的每个会话存储一些状态。
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
3.x 中没有明确定义的线程模型,尽管在 3.5 中尝试修复它的不一致性。 4.0 定义了严格的线程模型,帮助用户编写 ChannelHandler 而无需过多担心线程安全。
- Netty 永远不会并发调用 ChannelHandler 的方法,除非 ChannelHandler 使用 @Sharable 注释。 这与处理程序方法的类型无关 - 入站、出站或生命周期事件处理方法。
- 用户不再需要同步入站或出站事件处理程序方法。
- 4.0 不允许多次添加 ChannelHandler,除非使用 @Sharable 注释。
- Netty 的每个 ChannelHandler 方法调用之间始终存在先行关系。
- 用户不需要定义可变字段来保持处理程序的状态。
- 用户可以在向 ChannelPipeline 添加处理程序时指定 EventExecutor。
- 如果指定,ChannelHandler 的处理程序方法始终由指定的 EventExecutor 调用。
- 如果未指定,则处理程序方法始终由其关联的 Channel 注册到的 EventLoop 调用。
- 分配给处理程序或通道的 EventExecutor 和 EventLoop 始终是单线程的。
- 处理程序方法将始终由同一线程调用。
- 如果指定多线程EventExecutor或EventLoop,将首先选择其中一个线程,然后使用所选线程直到注销。
- 如果同一管道中的两个处理程序分配有不同的 EventExecutors,则它们会同时被调用。如果多个处理程序访问共享数据,即使共享数据仅由同一管道中的处理程序访问,用户也必须注意线程安全。
- 添加到 ChannelFuture 的 ChannelFutureListeners 始终由分配给未来关联 Channel 的 EventLoop 线程调用。
- ChannelHandlerInvoker 可用于控制 Channel 事件的顺序。 DefaultChannelHandlerInvoker 立即执行来自 EventLoop 线程的事件,并将来自其他线程的事件作为 EventExecutor 上的 Runnable 对象执行。请参阅以下示例,了解在与来自 EventLoop 线程和其他线程的 Channel 交互时可能产生的影响。
(强调是我的)