netty源码分析之-ReferenceCounted详解(9)

被引用计数包含的对象,能够显示的被垃圾回收。当初始化的时候,计数为1。retain()方法能够增加计数,release() 方法能够减少计数,如果计数被减少到0则对象会被显示回收,再次访问被回收的这些对象将会抛出异常。如果一个对象实现了ReferenceCounted,并且包含有其他对象也实现来ReferenceCounted,当这个对象计数为0被回收的时候,所包含的对象同样会通过release()释放掉。

由以下实现关系:

public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf{}
public abstract class AbstractByteBuf extends ByteBuf{}
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf>{}

AbstractReferenceCountedByteBuf是ReferenceCounted一个抽象实现类:

public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {

    private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater =
            AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");

    private volatile int refCnt = 1;
    ...
private ByteBuf retain0(int increment) {
        for (;;) {
            int refCnt = this.refCnt;
            final int nextCnt = refCnt + increment;

            // Ensure we not resurrect (which means the refCnt was 0) and also that we encountered an overflow.
            if (nextCnt <= increment) {
                throw new IllegalReferenceCountException(refCnt, increment);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) {
                break;
            }
        }
        return this;
    }
    ...
    private boolean release0(int decrement) {
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt < decrement) {
                throw new IllegalReferenceCountException(refCnt, -decrement);
            }

            if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) {
                if (refCnt == decrement) {
                    deallocate();
                    return true;
                }
                return false;
            }
        }
    }

对于release0方法,如果计数变成0则会回收相应的资源


对于retain0方法中通过compareAndSet来进行原子更新操作,确保多线程的正常计数操作,并通过自旋锁无限循环仅正确的cas操作才跳出。对于compareAndSet方法:

public abstract class AtomicIntegerFieldUpdater<T> {
    ...
    public abstract boolean compareAndSet(T obj, int expect, int update);
    ...
}

通过原子的方式来更新AtomicIntegerFieldUpdater更新器所持有的T对象中的某个成员变量,如果当前值等于期望值expect,那么会原子的更新成update。前提是,其他线程都是通过调用compareAndSet(弱原子性操作)来更新变量,否则无法保证操作是原子的(比如一些地方直接赋值)。compareAndSet是系统底层的实现,通过内存偏移量来完成整个操作。

对于AtomicIntegerFieldUpdater,是基于反射的能够原子更新给定类中的volatile int成员变量的一个工具类。这个类用来原子更新同一个节点中的多个变量,而做到不同的变量间原子操作单独不影响。

AtomicIntegerFieldUpdater重要要点:

  • 更新器更新的必须是int类型变量,不能是其包装类型(如果要更新包装类型变量,可以使用AtomicReferenceFieldupdater来更新)
  • 更新器更新的必须是volatile类型变量,确保线程之间共享变量时的立即可见性(volatile语义有两个:一个是禁止指令重排序,因为代码被编译器编译之后不一定会按照编写顺序执行;另一个是对变量的修改让多线程之间能够立刻可见,因为每个线程拥有自己的堆栈,修改之后会先保存到堆栈副本然后刷新到内存让其他线程可见,因此可能出现对应的修改在线程间出现短暂的不可见)
  • 变量不能是static的,必须要是实例变量。因为Unsafe.objectFieldOffset()方法不支持静态变量(CAS操作本质上是通过对象实例的偏移量来直接进行赋值)
  • 更新器只能修改它可见范围内的变量,因为更新器是通过反射来得到这个变量,如果变量不可见就会报错

对比JDK自带的AtomicInteger,如果netty底层通过AtomicInteger来维护,那么对于所有的ByteBuf对象都需要有对应的AtomicInteger来维护,而netty底层是需要用到大量的ByteBuf来做操的,可能会有许多的AtomicInteger变量,相比于一个全局的AtomicReferenceFieldupdater,在这里是static静态的,就能够维护所有的ByteBuf的引用计数,从而有一个性能上的提升。
官方更详细参考地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值