类定义
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
}
public abstract class AbstractByteBuf extends ByteBuf {
}
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
}
ByteBuf申明了对接口ReferenceCounted的实现,但是实际的代码支持AbstractReferenceCountedByteBuf中.
代码分析:
类AbstractReferenceCountedByteBuf中主要是实现了ByteBuf对接口ReferenceCounted的支持,没有其他代码.
refCntUpdater
静态变量refCntUpdater和静态初始化代码:
值得学习的 AtomicInteger 类,对与类中指定字段的精准更新。
private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
在类装载时初始化refCntUpdater以备用. 使用到PlatformDependent类(这块细节不展开).
refCnt
类属性refCnt的定义, 注意初始化值为1:
关键字volatile使得对refCnt 的访问都会基于主内存.refCnt()方法就只是简单返回这个refCnt属性.
private volatile int refCnt = 1;
public int refCnt() {
return this.refCnt;
}
类方法
retain() 方法
ReferenceCounted的工作原理: 当引用计数对象被初始化时, 引用计数器从1开始计数. retain()方法增加引用计数,而release()方法减少引用计数.如果引用计数被减到0,则这个对象就将被显式回收,而访问被回收的对象将通常会导致访问违规.
前面看到refCnt初始化值为1,和上面的原理一致. 继续看retain()方法的实现:
public ByteBuf retain() {
return this.retain0(1);
}
public ByteBuf retain(int increment) {
return this.retain0(ObjectUtil.checkPositive(increment, "increment"));
}
public static int checkPositive(int i, String name) {
if (i <= 0) {
throw new IllegalArgumentException(name + ": " + i + " (expected: > 0)");
} else {
return i;
}
}
private ByteBuf retain0(int increment) {
// 建立副本,这里注意
int refCnt;
int nextCnt;
do {
refCnt = this.refCnt;
nextCnt = refCnt + increment;
// 判断当前的引用数量,由于refCnt 初始化为1, 所以 next 一定大于 increment,
if (nextCnt <= increment) {
throw new IllegalReferenceCountException(refCnt, increment);
}
// 学习!!!
} while(!refCntUpdater.compareAndSet(this, refCnt, nextCnt));
return this;
}
retain(int increment) 方法的实现和retain()几乎完全相同,只是increment不是固定为1而已. 有点不太理解的是netty为什么不直接通过在retain()中调用retain(1)的方式来实现, 我能想到的理由就是retain()的调用非常频繁(远远超过retain(int increment)), 因此现在的做法可以带来少许的性能提升?
release() 方法
public boolean release() {
return this.release0(1);
}
public boolean release(int decrement) {
return this.release0(ObjectUtil.checkPositive(decrement, "decrement"));
}
private boolean release0(int decrement) {
// 建立副本!!!
int refCnt;
do {
refCnt = this.refCnt;
if (refCnt < decrement) {
throw new IllegalReferenceCountException(refCnt, -decrement);
}
} while(!refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement));
if (refCnt == decrement) {
this.deallocate();
return true;
} else {
return false;
}
}
// 显示回收对象
protected abstract void deallocate();
如果refCnt == decrement,意味着这次release()调用之后计数器会被置零.按照原理要求,“如果引用计数被减到0,则这个对象就将被显式回收”.因此调用deallocate()方法显式回收对象,返回值只有在deallocate()时才return true, 其他情况都是return false.
笔记关于 refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)
我的理解是在开始已经监控类 refCnt 的值:
private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
refCntUpdater.compareAndSet() 函数执行的是 先判断“refCnt"字段是值是否是期望的值 refCnt,也就是第二个参数,如果是则更新为 refCnt - decrement.
文章评论