使用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. selenium RC+JAVA 运行所遇到的问题

    1.报错一 Failed to start new browser session: java.lang.RuntimeException: Firefox 3 could not be found ...

  2. Quartz2D 编程指南(四)位图与图像遮罩、CoreGraphics 绘制 Layer

    概览 图形上下文 路径 颜色与颜色空间 变换 图案 阴影 渐变 透明层 Quartz 2D 中的数据管理 位图与图像遮罩 CoreGraphics 绘制 Layer 位图与图像遮罩 简介 位图与图像遮 ...

  3. web前端开发和后端开发有什么区别?

    web前端分为网页设计师.网页美工.web前端开发工程师 首先网页设计师是对网页的架构.色彩以及网站的整体页面代码负责 网页美工只针对UI这块儿的东西,比如网站是否做的漂亮 web前端开发工程师是负责 ...

  4. SVN File Name Case Sensitivity--SVN大小写问题

    from:http://www.visualsvn.com/support/topic/00019/ Windows has a case-insensitive file system. Unix ...

  5. 使用Microsoft Fakes隔离测试代码

    在单元测试(Unit Test)中我们遇到的问题之一是:假如被测试组件(类或项目)为A,组件A依赖于组件B,那么在组件A的单元测试ATest中测试A时,也需要依赖于B,在B发生改动后,就可能影响到A的 ...

  6. simple mail example for smtp debug

    vim /etc/mail.rc head /etc/rc.local | mail -s "test_email" pyz_sub1@mailtest.com

  7. c#字符显示转换{0:d}

    C#:String.Format数字格式化输出 : int a = 12345678; //格式为sring输出// Label1.Text = string.Format("asdfads ...

  8. 命令行下Git的使用

    命令行下Git的使用 写在前边的话 以自己即将进行的毕设项目为例,进行Git使用的简易说明.不过由于校园网络的限制,故使用GitOSC. 快速开始 本次git使用位于自己的个人PC上,所以将个人的Gi ...

  9. 校内通知-Notifications表增加老师,家长,学生发送范围字段

    老师发送范围:TReceiveRange 家长发送范围:PReceiveRange 学生发送范围:SReceiveRange alter table Notifications add TReceiv ...

  10. java关键字 super 和 this

    简单粗暴的说就是: super: 是指父类,想要在子类方法中调用父类的实例变量或方法可以通过super 来访问 this:是指当前类,想要访问当前类的实例变量和方法可以使用this,同时可以省略