private final void addCount(long x, int check) {
//as:cells
//b:base
//s:table
CounterCell[] as; long b, s;
//条件1:true表示as数组不为空,需要通过hash计算找到自己的cell
// false表示as数组为空,将当前数据累加到base
//条件2:true表示cas失败,即发生冲突,所以需要创建cell数组
// false表示cas成功,所以不需要创建cell数组
if ((as = counterCells) != null ||
!U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
//a:当前线程hash之后对应的cell
//v:期望值
//m:cell数组的长度
CounterCell a; long v; int m;
//true:表示未发生竞争
boolean uncontended = true;
//条件1:as == null || (m = as.length - 1) < 0
//true:说明线程是通过cas失败才进入的
//条件2:a = as[ThreadLocalRandom.getProbe() & m]) == null
//true:当前cell是空的,需要线程来初始化
//条件3:!(uncontended =U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
//true:当前线程cas更新当前cell失败,需要进行重试
if (as == null || (m = as.length - 1) < 0 ||
(a = as[ThreadLocalRandom.getProbe() & m]) == null ||
!(uncontended =
U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
fullAddCount(x, uncontended);
return;
}
if (check <= 1)
return;
//当前散列表的元素个数
s = sumCount();
}
//表示一定是put来调用addcount
if (check >= 0) {
//tab:table数组
//nt:nextTable
//n:table数组的长度
//sc:sizeCtl的临时值
Node<K,V>[] tab, nt; int n, sc;
//条件1:s >= (long)(sc = sizeCtl
//表示sizeCtl是一个负数,正在扩容中
//条件2:(tab = table) != null 恒成立
//条件3:(n = tab.length) < MAXIMUM_CAPACITY,基本上也恒成立
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n);
//table正在扩容
if (sc < 0) {
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
transferIndex <= 0)
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
transfer(tab, nt);
}
else if (U.compareAndSwapInt(this, SIZECTL, sc,
(rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null);
s = sumCount();
}
}
}
ConcurrentHashMap源码剖析03_addCount()方法详解
最新推荐文章于 2024-07-22 14:15:06 发布