netty的对象的生命周期管理——引用计数
来源:互联网 发布:串口调试助手软件 编辑:程序博客网 时间:2024/05/17 22:11
一、何谓引用计数
1.1 引用计数
引用计数是一种简单高效的垃圾回收机制,当一个新的引用指向对象的时候,增加引用计数;去掉一个引用,就减小一个引用计数;当引用计数减到0的时候,就释放掉这个引用计数。
1.2 引用计数的增减
对于一个引用计数的对象,最核心的操作就是引用计数的增减。但是,在一个并发场景下,必须保证引用计数增减的原子性。最简单的实现方法如下:
private static class AtomicIntSync implements Atomic { private int i = 0; public AtomicIntSync(int i) { this.i = i; } @Override public synchronized int incrementAndGet() { return ++i; } }
这种方法通过synchonized关键字,为自增操作加锁,而且java对这个关键字做了很多的优化,相对而言性能还是挺高的。
稍微复杂一点的方式是使用CAS(Compare and swap)的方式,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,实现如下:
private static class AtomicIntCas implements Atomic { private volatile int i = 0; private static final Unsafe unsafe; private static long off; static { Unsafe tmp = null; try { //获取unsafe Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); tmp = (Unsafe) field.get(null); //获取i字段在类中的偏移 off = tmp.fieldOffset(AtomicIntCas.class.getDeclaredField("i")); } catch (Throwable e) { e.printStackTrace(); } unsafe = tmp; } public AtomicIntCas(int i) { this.i = i; } @Override public int incrementAndGet() { for (;;) { int m = i; int add = m + 1; if (unsafe.compareAndSwapInt(this, off, m, add)) { return add; } } } }整个性能对比的程序如附件所示,运行后的性能对比曲线如下,(x轴为线程的数量,y轴为每一个线程运行的时间):
由上图可知,CAS方式整体性能是好于使用synchronized的这种锁的方式的。
二、引用计数的应用
引用计数的应用非常多,大名鼎鼎的Python语言其简单对象的垃圾回收机制就用的引用计数,netty的大量数据结构也使用的是引用计数。因为引用计数的垃圾回收实现简单,而且非常高效,特别是在分布式环境中,其性能真心杠杠的。
三、引用计数的局限
引用计数很难解决的场景是:A引用B,B同时引用A,当A和B都不使用了,A和B的引用都会是1,导致这种场景下的引用计数无法变成0,导致A和B都不能被释放。
四、netty的引用计数的实现
netty的引用计数的接口为io.netty.util.ReferenceCounted,netty很多重要的数据结构都是继承这个接口,比如ByteBuf,其核心实现参考:io.netty.util.AbstractReferenceCounted,其实现方式和上面的CAS的实现方法原理基本一致。
过程是:
1、通过Unsafe的方法,计算引用计数字段在AbstractReferenceCounted类中的偏移
2、通过Unsafe提供的CAS方法,将新的数据搬迁到引用计数字段所在的位置(AbstractReferenceCounted对象的地址+偏移)
3、如果CAS操作成功,就返回;否则计算新的引用计数,然后调用步骤2
五、netty的内存泄露检查
详见下一篇文章~
六、netty的引用计数的使用举例
- netty的对象的生命周期管理——引用计数
- C++的引用计数j控制智能指针——>Java的引用计数管理共享对象
- 关于内存管理引用计数与变量生命周期的关系
- C++对象生命周期管理--通过引用计数指针对象来封装管理对象生命周期
- 引用计数自动管理对象的生存周期
- retain 引用计数:两个所有者对同一个对象的管理
- 手动内存管理-对象的引用计数
- OC的内存管理 与 引用计数
- OC使用引用计数的内存管理
- objective-c 的引用计数管理
- OC的内存管理引用计数机制
- 线程核心对象的引用计数
- 获取内核对象的引用计数
- ARC下查看对象的引用计数
- 引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法
- C++内存管理——引用计数
- OC内存管理之—引用计数
- 避免重复的对象构建 ——Reference Counting(引用计数)技术
- UESTC 84 Binary Operations (dp+二进制枚举)
- 【线性代数公开课MIT Linear Algebra】 第六课 AX=b与列空间、零空间
- POJ1861 - Network (并查集,最小生成树)
- 11个可能不知道的Python库
- JavaWeb三层结构实例
- netty的对象的生命周期管理——引用计数
- HDU 4020 Ads Proposal
- C++细节问题
- Python中的对象的排序
- POJ1308 - Is It A Tree? (并查集)
- 15个易遗忘的Java问题
- Python中深拷贝与浅拷贝
- 深入源码解析Android中Loader、AsyncTaskLoader、CursorLoader、LoaderManager
- 数据库增删改查语句