使用Netty编程时,我们经常会从用户线程,而不是Netty线程池发起write操作,因为我们不能在netty的事件回调中做大量耗时操作。那么问题来了 –

1, writeAndFlush是线程安全的吗?

2, 是否使用了锁,导致并发性能下降呢

我们来看代码 – 在DefaultChannelHandlerContext中

@Override
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
DefaultChannelHandlerContext next;
next = findContextOutbound(MASK_WRITE);
ReferenceCountUtil.touch(msg, next);
next.invoker.invokeWrite(next, msg, promise);
next = findContextOutbound(MASK_FLUSH);
next.invoker.invokeFlush(next);
return promise;
}

在DefaultChannelHandlerInvoker.java中

@Override
public void invokeWrite(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (msg == null) {
throw new NullPointerException("msg");
}
if (!validatePromise(ctx, promise, true)) {
// promise cancelled
ReferenceCountUtil.release(msg);
return;
} if (executor.inEventLoop()) {
invokeWriteNow(ctx, msg, promise);
} else {
AbstractChannel channel = (AbstractChannel) ctx.channel();
int size = channel.estimatorHandle().size(msg);
if (size > 0) {
ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
// Check for null as it may be set to null if the channel is closed already
if (buffer != null) {
buffer.incrementPendingOutboundBytes(size);
}
}
safeExecuteOutbound(WriteTask.newInstance(ctx, msg, size, promise), promise, msg);
}
}
private void safeExecuteOutbound(Runnable task, ChannelPromise promise, Object msg) {
try {
executor.execute(task);
} catch (Throwable cause) {
try {
promise.setFailure(cause);
} finally {
ReferenceCountUtil.release(msg);
}
}
}

可见,writeAndFlush如果在Netty线程池内执行,则是直接write;否则,将作为一个task插入到Netty线程池执行。

《Netty权威指南》写到
通过调用NioEventLoop的execute(Runnable task)方法实现,Netty有很多系统Task,创建他们的主要原因是:当I/O线程和用户线程同时操作网络资源时,为了防止并发操作导致的锁竞争,将用户线程的操作封装成Task放入消息队列中,由I/O线程负责执行,这样就实现了局部无锁化。

参考
http://www.cnblogs.com/zemliu/p/3667332.html
http://netty.io/5.0/xref/io/netty/channel/DefaultChannelHandlerInvoker.html
http://www.infoq.com/cn/articles/netty-version-upgrade-history-thread-part/

Netty : writeAndFlush的线程安全及并发问题的更多相关文章

  1. (转)Netty : writeAndFlush的线程安全及并发问题

    rocketmq用netty实现的网络连接,发现它多个线程掉用一个channel连接,所以这个是线程安全的? 使用Netty编程时,我们经常会从用户线程,而不是Netty线程池发起write操作,因为 ...

  2. Netty writeAndFlush() 流程与异步

    Netty writeAndFlush()方法分为两步, 先 write 再 flush @Override public ChannelFuture writeAndFlush(Object msg ...

  3. 设计模式:基于线程池的并发Visitor模式

    1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...

  4. java线程安全之并发Queue

    关闭 原 java线程安全之并发Queue(十三) 2017年11月19日 23:40:23 小彬彬~ 阅读数:12092更多 所属专栏: 线程安全    版权声明:本文为博主原创文章,未经博主允许不 ...

  5. 性能测试:深入理解线程数,并发量,TPS,看这一篇就够了

    并发数,线程数,吞吐量,每秒事务数(TPS)都是性能测试领域非常关键的数据和指标. 那么他们之间究竟是怎样的一个对应关系和内在联系? 测试时,我们经常容易将线程数等同于表述为并发数,这一表述正确吗? ...

  6. 文件数据库sqlite3 C++ 线程安全和并发

    转载:https://www.cnblogs.com/feng9exe/p/10682567.html(线程安全和并发) 转载:https://juejin.im/post/5b7d8522e51d4 ...

  7. 如何理解 jmeter 的线程数与并发数之间的关系

    https://blog.csdn.net/weixin_39955351/article/details/110548162 多个线程组的并发是如何计算的?

  8. websocket(三) 进阶!netty框架实现websocket达到高并发

    引言: 在前面两篇文章中,我们对原生websocket进行了了解,且用demo来简单的讲解了其用法.但是在实际项目中,那样的用法是不可取的,理由是tomcat对高并发的支持不怎么好,特别是tomcat ...

  9. websocket 进阶!netty框架实现websocket达到高并发

    引言: 在前面两篇文章中,我们对原生websocket进行了了解,且用demo来简单的讲解了其用法.但是在实际项目中,那样的用法是不可取的,理由是tomcat对高并发的支持不怎么好,特别是tomcat ...

随机推荐

  1. golang 环境一键式配置

    在window下,通过以下bat,自动设置环境变量,启动终端,并cd到gopath目录 set goroot=c:\go set gopath=d:\go @start "start gol ...

  2. Google Supersonic列存储查询库的介绍、安装、测试

    查询引擎库介绍: http://www.infoq.com/cn/news/2012/10/Google-Supersonic/ Supersonic是一个面向列存储数据库的查询引擎库,它提供了一组数 ...

  3. ui-grid

    html代码: <html ng-app="myApp">       <head>         <meta charset="utf- ...

  4. iptables的conntrack表满了导致访问网站很慢

    iptables的conntrack表满了导致访问网站很慢 转载自:https://my.oschina.net/jean/blog/189935 检查系统conntrack表是否满 现象:突然发现访 ...

  5. Android 基于Android的手机邮件收发(JavaMail)之一(准备工作)

    界面一共是五个界面,分别是welcomeActivity,ReceiveAndSendActivity,ReceiveListActivity,SendMailActivity,MailDetails ...

  6. 原生node的header

    首先引入http模块 获取http.ServerResponse对象的方式,1.http.createServer(function(req,res){}) 其中res是http.ServerResp ...

  7. SpringMVC常用配置-配置DispatcherServlet映射请求路径的方式

  8. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版新增查询引擎管理

    欲了解V3.0版本的相关内容可查看下面的链接地址. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版本发布 RDIFramework.NET — 基于.NET的快速信 ...

  9. Ubuntu Kylin 14.04下配置JDK1.8

    1.源码包准备: 首先到官网下载jdk,http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.h ...

  10. js 实现类似php函数number_format的功能

    今天同事在做一个功能的时候需要使用js来实现类似php函数number_format的功能,最后就有了下面的方法,可以实现了: /** * number_format * @param number ...