顾名思义,引用计数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();