原文链接 Netty中ByteBuf的引用计数线程安全的实现原理

代码仓库地址

ByteBuf 实现了ReferenceCounted 接口,实现了引用计数接口,该接口的retain(int) 方法为了保证线程安全使用了自旋锁来确保操作安全,那么选择了比较重要的实现类AbstractReferenceCountedByteBuf 来查看这一特性.

在JDK 1.5 之后,JDK的并发包提供了Atomic* 的相关类,来帮助开发者更好的完成并发操作,这里我们学习使用CAS来实现线程安全,CAS就是ComposeAndSet,中文含义,比较And更新,我们来看一个例子,具体的说明在注释中!

static class Increment {

    // volatile 保证了线程可见性,但是没有保证按成安全性
private volatile int i; // 声明CAS的抽象类
private static AtomicIntegerFieldUpdater<Increment> updater; static {
// 通过静态方法创建CAS的具体实例
// 第一个参数表示维护的Integer所在的类的class
// 第二个参数表示维护的Integer变量的名称
updater = AtomicIntegerFieldUpdater.newUpdater(Increment.class, "i");
} /**
* 构造初始化函数
*
* @param i
*/
public Increment(int i) {
this.i = i;
} /** 自增一个 */
public void increment() {
increment(1);
} /**
* 重载自增方法
*
* <p>该方法具体实现了CAS的代码逻辑,重在均在下面的for循环中
*
* @param increment
*/
public void increment(int increment) {
// 创建一个死循环,compareAndSet检查不通过的时候,重新获取新的值尝试更新
for (; ; ) {
// 保存当前线程更新的值的状态
int oldI = this.i;
final int newValue = oldI + increment;
// 校验值是否更新完成
if (newValue <= increment) {
throw new IllegalArgumentException("非法的参数异常");
}
// 如果CAS更新完成,则退出循环,否则打印重试日志
if (updater.compareAndSet(this, oldI, newValue)) {
break;
}
System.out.println("发生多线程并发,CAS正常重新尝试");
}
}
}

实现了自增的CAS代码之后,我们创建一个MyRunnable 继承Runnable 在run() 方法中实现Increment 实例的自增,具体代码如下:

  static class MyRunnable implements Runnable {

    private Increment increment;

    public MyRunnable(Increment increment) {
this.increment = increment;
} @Override
public void run() {
increment.increment();
}
}

在main() 方法中我们创建一个Increment 示例对象,构造参数传1,然后创建50个线程,同时启动,观察最终的结果, 多次运行观察是否能实现线程安全.

  public static void main(String[] args) throws InterruptedException {
Increment increment = new Increment(1);
for (int i = 0; i < 50; i++) {
new Thread(new MyRunnable(increment)).start();
}
// 延时4s, 等待所有线程执完成后,输出i
TimeUnit.SECONDS.sleep(4);
System.out.println(increment.i);
}

最后输出结果为51,可见CAS 能够实现多线程安全的问题,相对于RelockCount和重量级的synchronized 各有各的适合场景,下面回到Netty的自旋锁的问题上来,可以看到下面的代码和上面的示例是类似的,Netty依靠这个方法来完成ByteBuf的引用计数,确保多线程操作ByteBuf的时候引用计数不会出现多线程的问题,

下面的代码是引用了Netty5 的 io.netty.buffer.AbstractReferenceCountedByteBuf 类的部分代码,有兴趣的朋友可以下载该框架的源码,找到该文件看一下。

    private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater;
static {
AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater =
PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
if (updater == null) {
updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
}
refCntUpdater = updater;
} @Override
public ByteBuf retain(int increment) {
if (increment <= 0) {
throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)");
}
for (;;) {
int refCnt = this.refCnt;
if (refCnt == 0) {
throw new IllegalReferenceCountException(0, increment);
}
if (refCnt > Integer.MAX_VALUE - increment) {
throw new IllegalReferenceCountException(refCnt, increment);
}
if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) {
break;
}
}
return this;
}

Netty中ByteBuf的引用计数线程安全的实现原理的更多相关文章

  1. 【Netty官方文档翻译】引用计数对象(reference counted objects)

    知乎有关于引用计数和垃圾回收GC两种方式的详细讲解 https://www.zhihu.com/question/21539353 原文出处:http://netty.io/wiki/referenc ...

  2. OC中的自动引用计数

    目录: 1,自动引用计数的定义 2,强引用和弱引用 3,类比手动引用 4,循环引用 5,CoreFoundation 内容: 自动引用计数的定义: (Automatic Reference Count ...

  3. Netty中ByteBuf 的零拷贝

    转载:https://www.jianshu.com/p/1d1fa2fe1ed9 此文章已同步发布在我的 segmentfault 专栏. 根据 Wiki 对 Zero-copy 的定义: &quo ...

  4. Netty源码分析之ByteBuf引用计数

    引用计数是一种常用的内存管理机制,是指将资源的被引用次数保存起来,当被引用次数变为零时就将其释放的过程.Netty在4.x版本开始使用引用计数机制进行部分对象的管理,其实现思路并不是特别复杂,它主要涉 ...

  5. netty中的ByteBuf

    网络数据的基本单位总是字节.Java NIO 提供了 ByteBuffer 作为它 的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐. Netty 的 ByteBuffer 替代品是 ByteB ...

  6. netty系列之:不用怀疑,netty中的ByteBuf就是比JAVA中的好用

    目录 简介 ByteBuf和ByteBuffer的可扩展性 不同的使用方法 性能上的不同 总结 简介 netty作为一个优秀的的NIO框架,被广泛应用于各种服务器和框架中.同样是NIO,netty所依 ...

  7. netty 引用计数对象(reference counted objects)

    [Netty官方文档翻译]引用计数对象(reference counted objects) http://damacheng009.iteye.com/blog/2013657

  8. netty中的channelPipeline在编程中的作用

    在netty编程中我们绝大多数是要是用nio的,nio相比传统的io更加高效,而nio中核心概念离不开channel,buffer,selector三个重要的对象. 那么在netty中有一个chann ...

  9. 【Netty】Netty之ByteBuf

    一.前言 前面已经学习了Netty中传输部分,现在接着学习Netty中的ByteBuf. 二.ByteBuf 2.1 ByteBuf API 在网络上传输的数据形式为Byte,Java NIO提供了B ...

随机推荐

  1. 前端笔记之NodeJS(二)路由&REPL&模块系统&npm

    一.路由机制(静态资源文件处理) 1.1 Nodejs没有根目录 MIME类型:http://www.w3school.com.cn/media/media_mimeref.asp 在Apache中, ...

  2. springcloud情操陶冶-springcloud config server(三)

    承接前文springcloud情操陶冶-springcloud config server(二),本文就不讲述server了,就简单阐述下client的应用 前话 config server在引入的时 ...

  3. java之servlet入门操作教程一续

    本节主要是在java之servlet入门操作教程一  的基础上使用myeclipse实现自动部署的功能 准备: java之servlet入门操作教程一 中完成myFirstServlet项目的创建: ...

  4. JSON Web Token入门教程

    目录 一.跨域认证的问题 二.JWT的原理 三.JWT的数据结构 3.1Header 3.2Payload 3.3 Signature 3.4 Base64URL 四.JWT的使用方式 五.JWT的几 ...

  5. Fundebug微信小程序错误监控插件更新至1.1.0,新增test()与notifyHttpError()方法

    摘要: 1.1.0新增fundebug.test()和fundebug.notifyHttpError()方法,同时大小压缩至15K. Fundebug是专业的小程序BUG监控服务,可以第一时间为您捕 ...

  6. Dynamics 365 CE在Pre Delete插件中应用Image

    微软动态CRM专家罗勇 ,回复327或者20190428可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! 在插件中限制记录的删除是常见的场景,比如根据statuscode ...

  7. Android路由框架-ARouter详解

    文章大纲 一.页面路由基本介绍1.什么是页面路由2.为什么要使用页面路由二.页面路由框架ARouter介绍1.常用功能介绍2.常见应用场景三.源码下载四.参考文章   一.页面路由基本介绍 1.什么是 ...

  8. ionic3 生命周期

    ionic3 总共有8个钩子函数,分别是:onPageLoaded,onPageWillEnter,onPageDidEnter,onPageWillLeave,onPageDidLeave,onPa ...

  9. July 05th. 2018, Week 27th. Thursday

    Pleasure in the job puts perfection in the work. 乐于工作才能有完美表现. From Aristole. Do you want promotion? ...

  10. spring boot 2.0 集成 shiro 和 pac4j cas单点登录

    新开的项目,果断使用  spring boot  最新版本  2.0.3 ,免得后期升级坑太多,前期把雷先排了. 由于对 shiro 比较熟,故使用 shiro 来做权限控制.同时已经存在了 cas  ...