AbstractReferenceCountedByteBuf 引用计数

本文介绍了Netty框架中的引用计数ByteBuf基类AbstractReferenceCountedByteBuf,详细解析了其内部实现原理,包括引用计数的增加与减少、CAS操作的应用以及Unsafe API的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

顾名思义,引用计数bytebuf基类。
在介绍这个类之前,先介绍几个点预热一下。
AtomicIntegerFieldUpdater  整型字段的更新器,保证更新integer字段原子性操作

CAS :compareAndSet,获取当前变量的值,根据变量计算出一个新值,如果这时变量的值没有变化,就用新值更新变量,如果有变化则不更新。
伪代码:
for(;;;)
{
    获取变量值A
    计算变量的新值保存在B
    如果变量A的值未变化,用B的值更新A,退出循环
    如果变量A的值有变化,继续这个循环,直至更新成功才退出循环
}

unsafe.objectFieldOffset  获取成员变量的偏移地址
jvm为每个类实例分配了内存基地址,类的每个成员变量都在内存中都有固定的偏移量,通过基地址+偏移量可以直接获取修改成员变量

/**
 * Abstract base class for {@link ByteBuf} implementations that count references.
 */
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {

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

    private static final long REFCNT_FIELD_OFFSET;

    static {
        long refCntFieldOffset = -1;
        try {
            if (PlatformDependent.hasUnsafe()) {
                //底层是通过unsafe.objectFieldOffset获取到成员变量refCnt在AbstractReferenceCountedByteBuf类的地址偏移量
                refCntFieldOffset = PlatformDependent.objectFieldOffset(
                        AbstractReferenceCountedByteBuf.class.getDeclaredField("refCnt"));
            }
        } catch (Throwable t) {
            // Ignored
        }

        REFCNT_FIELD_OFFSET = refCntFieldOffset;
    }

    @SuppressWarnings("FieldMayBeFinal")
    private volatile int refCnt = 1;

    protected AbstractReferenceCountedByteBuf(int maxCapacity) {
        super(maxCapacity);
    }

    @Override
    public final int refCnt() {
        if (REFCNT_FIELD_OFFSET >= 0) {
            // Try to do non-volatile read for performance.
           //底层调用了UNSAFE.getInt(object, fieldOffset)方法,通过类成员变量的偏移地址,直接读取内存值,保证获取到最新的变量值
            return PlatformDependent.getInt(this, REFCNT_FIELD_OFFSET);
        } else {
            return refCnt;
        }
    }

    /**
     * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly
     */
    protected final void setRefCnt(int refCnt) {
        this.refCnt = refCnt;
    }

    //添加引用计数,
    @Override
    public ByteBuf retain() {
        //用for循环保证可以更新成功,并且不会冲突
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt == 0) {
                throw new IllegalReferenceCountException(0, 1);
            }
            if (refCnt == Integer.MAX_VALUE) {
                throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) {
                break;
            }
        }
        return this;
    }

    @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;
    }

    //减少引用计数
    @Override
    public final boolean release() {
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt == 0) {
                throw new IllegalReferenceCountException(0, -1);
            }

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

    @Override
    public final boolean release(int decrement) {
        if (decrement <= 0) {
            throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)");
        }

        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;
            }
        }
    }

    /**
     * Called once {@link #refCnt()} is equals 0.
     */
    protected abstract void deallocate();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值