Netty-ChannelHandler并发安全分析

本文探讨Netty中ChannelHandler的并发安全问题,包括串行执行的ChannelHandler、跨链路共享的ChannelHandler及并发场景总结,强调了线程安全的重要性。

ChannelHandler是Netty中使用最广的接口,Netty提供了大量内置的ChannelHandler实现类,包括编解码、SSL、日志打印等等。用户通过实现ChannelHandler接口,来接口和发送业务消息,并进行业务逻辑处理。


   Netty ChannelHandler并发安全问题
        串行执行的ChannelHandler
        跨链路共享的ChannelHandler
        ChannelHandler并发场景总结


Netty ChannelHandler并发安全问题

     业务有一个非线程安全的类ThreadUnsafeClass,这个类会在业务ChannelHandler的channelRead方法中被调用。下面这样的调用方法在多线程环境是否安全:

public class ServiceHandler extends ChannelInboundHandlerAdapter{
   
   
	private ThreadUnsafeClass unsafe = new ThreadUnsafeClass(); //非线程安全类
	public void channelRead(ChannelHandlerContext ctx, Object msg){
   
   
		//此处调用是否正确?
		unsafe.doSomething(ctx, msg);
	}
}

串行执行的ChannelHandler

     如果ChannelHandler是非共享的,则它就是线程安全的,原因:当链路完成初始化会创建ChannelPipeline,每个channel对应一个ChannelPipeline实例,业务的ChannelHandler会被实例化并加入ChannelPipeline中执行,由于某个Channel只能被特定的NioEventLoop线程执行,因此ChannelHandler不会被并发调用,不用考虑线程安全问题,相关源码:

.handler(new ChannelInitializer<SocketChannel>(){
   
   
	@Override
	public void initChannel(SocketChannel ch) throws Exception {
   
   
		ch.pipeline().addLast(
			new NoThreadSecurityClientHandler()
		);
	}
});

     业务可能会多线程调用ChannelHandlerContext或者Channel的write方法,这会不会导致多个业务线程并发调用ChannelHandler呢?答案是并不会产生并发安全问题。在执行write操作时,会判断是否是下一个要执行wirte操作的AbstractChannelHandlerContext的EventExecutor线程,如果不是则将write操作封装成AbstractWriteTask放入线程任务队列异步执行,原调用线程返回。如果业务的ChannelHandler没有指定EventExecutor,则使用的就是消息读写对应的NioEventLoop线程。因此即便多个业务线程并发调用某个Channel,也不会产生多个线程并发访问业务ChannelHandler的问题。源码如下(AbstractChannelHandlerContext类):

private void write(Object msg, boolean flush, ChannelPromise promise){
   
   
	AbstractChannelHandlerContext next = findContextOutbound
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值