LongAdder中的longAccumulate方法中关于rehash的问题?
longAccumulate方法中有一个地方我觉得不需要rehash,搞不清楚为什么这里需要rehash。直接贴代码吧,重点问题我写在了这段代码的下面。
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) {
int h;
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
h = getProbe();
wasUncontended = true;
}
// 是否需要扩容
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
// 判断cells非空并且其长度不为0,说明不存在竞争
if ((as = cells) != null && (n = as.length) > 0) {
// 获取下标位置的Cell如果为空
if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) {}
// 表示暂时还不需要扩容
collide = false;
}
// 说明cas失败,在add方法中,能走到以下的else说明当前下标位置已经有东西了
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash 发现有竞争后rehash重试
// 看一下能不能直接CAS设置成功,不能的话继续向下走
else if (a.cas(v = a.value, ((fn == null) ? v + x :
fn.applyAsLong(v, x)))) // 如果再次设置失败,继续向下执行elseif
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide) //
collide = true; // 只能理解为再试一次了,再试一次还是不行那就只能扩容了
else if (cellsBusy == 0 && casCellsBusy()) {
}
// 这里会rehash
h = advanceProbe(h);
}
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
}
else if (casBase(v = base, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break; // Fall back on using base
}
}
我们看下这段代码:
if ((a = as[(n - 1) & h]) == null) { if (cellsBusy == 0) {}
// 表示暂时还不需要扩容
collide = false;
}
如果cellsBusy不为0,则表示CAS锁正在被占用,然后会执行collide=false这句代码,再然后执行完这个条件分支后会进行rehash,就是执行 h = advanceProbe(h);这句代码,我想问,为什么需要rehash啊?as[(n - 1) & h]这个位置不已经是空的吗?只是占时没获取到CAS锁而已,所以才没有向里面填值,但是我觉得只要重循环一下,如果cellsBusy未被占用,直接继续在这个位置赋值就行,为什么还要rehash换位置呢?
回答:
那万一下一次来它还是获取不到锁呢?还不如rehash让它重新找个坑儿
回答:
https://segmentfault.com/a/1190000039667702
需要 rehash ,说明前 Cell组 冲突性大,rehash 换个冲突性小的节点叠加。
以上是 LongAdder中的longAccumulate方法中关于rehash的问题? 的全部内容, 来源链接: utcz.com/p/944699.html