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

回到顶部