public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable {
一些成员变量
//扩容的最大容量限制
private static final int MAXIMUM_CAPACITY = 1 << 30;
//默认容量
private static final int DEFAULT_CAPACITY = 16;
//扩容因子,当达到容量达到n*LOAD_FACTOR时,就会扩容
private static final float LOAD_FACTOR = 0.75f;
//超过这个值会扩容或建红黑树
static final int TREEIFY_THRESHOLD = 8;
//从链表升级为红黑树的阈值
static final int MIN_TREEIFY_CAPACITY = 64;
//多线程扩容,这个表示每个线程最少负责迁移数据的数量
private static final int MIN_TRANSFER_STRIDE = 16;
//下面都是hash值
static final int MOVED = -1; //表示在扩容
static final int TREEBIN = -2; //表示是树节点
static final int RESERVED = -3;
//hash值取除最高一位以外的31位
static final int HASH_BITS = 0x7fffffff;
//CPU数量
static final int NCPU = Runtime.getRuntime().availableProcessors();
//装载数据的数组
transient volatile Node<K,V>[] table;
//扩容用的新数组
private transient volatile Node<K,V>[] nextTable;
//没有并发时的计数
private transient volatile long baseCount;
//达到该值就会扩容
private transient volatile int sizeCtl;
构造方法
public ConcurrentHashMap(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException();
//如果initialCapacity大于MAXIMUM_CAPACITY的一半就直接赋值为MAXIMUM_CAPACITY
//否则赋值为1.5倍initialCapacity+1,然后向上去最近2的次方的数
int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
MAXIMUM_CAPACITY :
tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
this.sizeCtl = cap;
}
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
if (initialCapacity < concurrencyLevel) // Use at least as many bins
initialCapacity = concurrencyLevel; // as estimated threads
long size = (long)(1.0 + (long)initialCapacity / loadFactor);
int cap = (size >= (long)MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY : tableSizeFor((int)size);
this.sizeCtl = cap;
}
数据都封装到Node类中
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;//哈希值
final K key;//键
volatile V val;//数据
volatile Node<K,V> next;//下一个节点
Node(int hash, K key, V val, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.val = val;
this.next = next;
}
...
}
下面从增删查分析源码
分析之前,先了解下ConcurrentHashMap类中CAS操作,主要有以下三个方法
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
//返回第i个Node元素,i左移ASHIFT位+第一个元素的地址ABASE
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
Node<K,V> c, Node<K,V> v) {
//CAS方式更新第i个位置的元素
return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}
static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
//cas赋值数组第i个元素
U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
}
ASHIFT、ABASE在静态代码块中进行赋值
Class<?> ak = Node[].class;
//arrayBaseOffset: 返回当前数组第一个元素地址相对于数组起始地址的偏移值
ABASE = U.arrayBaseOffset(ak);
//arrayIndexScale: 返回当前数组一个元素占用的字节数,在本例中返回4。
int scale = U.arrayIndexScale(ak);
if ((scale & (scale - 1)) != 0)//必须是2的指数
throw new Error("data type scale not a power of two");
//Integer.numberOfLeadingZeros:返回int数字的高位直到第一个非0位的位数,如4,返回29(100,前面29个0)
//ASHIFT作用:可方便地利用左移ASHIFT位拿到数组第i个元素的地址偏移量
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
这里CAS操作数组,可以这么理解:拿到数组第一个元素的偏移地址p,然后拿到每个数据所占的字节数c,那么第i个元素偏移地址就是p+i*c。所以可以利用左移ASHIFT位来拿到第i个元素的偏移量,再加上ABASE,就是第i个元素相对于数组起始地址的偏移量。
1. 增加数据
public V put(K key, V value) {
//插入数据,存在就覆盖
return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
//【标记1】对key的哈希值进行处理,使得更离散
int hash = spread(key.hashCode());
int binCount = 0;//统计链表长度
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();//【标记2】一开始没初始化数组
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {//用(n - 1) & hash取到数组下标,发现其元素为null
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break;//直接CAS成功添加了一个新节点
}
else if ((fh = f.hash) == MOVED)//MOVED是数据迁移标志
tab = helpTransfer(tab, f);//【标记3】正在数据迁移,去帮助数据迁移
else {
V oldVal = null;
synchronized (f) {//锁住当前节点
if (tabAt(tab, i) == f) {
if (fh >= 0) {//说明是链表结构
binCount = 1;//计算链表节点数量
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;//找到原来的值
if (!onlyIfAbsent)
e.val = value;//只用onlyIfAbsent为false才更新值
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {//到了链尾
//这里新建一个节点插入
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) {
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}
}
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);//【标记4】超过阀值开始考虑建红黑树
if (oldVal != null)
return oldVal;
break;
}
}
}
//当对应的key原先不存在才到这里
//【标记5】增加计数
addCount(1L, binCount);
return null;
}
ConcurrentHashMap插入需要保证线程安全,所以操作数据用了CAS方式,另外当插入的时候如果正好在扩容,就会去帮忙扩容,最后插入成功后会进行判断是否需要扩容,是否要增加计数。
【标记1】hash值处理,使映射更加离散
static final int spread(int h) {
//异或,然后再取低31位
//HASH_BITS = 0x7fffffff;
return (h ^ (h >>> 16)) & HASH_BITS;
}
【标记2】初始化数组
private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) {
if ((sc = sizeCtl) < 0)
Thread.yield(); // 被其他线程抢先了,睡眠一下,醒来再自旋判断
else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {//CAS方式设置为-1,防止多线程同时初始化
try {
if ((tab = table) == null || tab.length == 0) {
//如果sizeCtl小于等于0 ,会赋值为DEFAULT_CAPACITY
int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
//申请数组空间
@SuppressWarnings("unchecked")
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt;
//n-0.25n = 0.75n
sc = n - (n >>> 2);
}
} finally {
sizeCtl = sc;
}
break;
}
}
return tab;
}
数组一开始初始化容量是根据sizeCtl的值来决定的,然后sizeCtl会被更新为容量的0.75倍。
【标记3】帮助数据迁移
final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
Node<K,V>[] nextTab; int sc;
//必须要原先tab不为null,而且f是ForwardingNode,并且新数组已经被赋值
if (tab != null && (f instanceof ForwardingNode) &&
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
int rs = resizeStamp(tab.length);
while (nextTab == nextTable && table == tab &&
(sc = sizeCtl) < 0) {
//下面的条件不怎么看懂,大概是在控制帮助数据迁移的线程数量
// 最后的transferIndex <= 0说明数据迁移已经全部由其他线程完成或正在进行
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || transferIndex <= 0)
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
transfer(tab, nextTab);//进行数据迁移
break;
}
}
return nextTab;
}
//上面条件不满足就返回旧的数组
return table;
}
【标记4】超过阀值开始考虑建红黑树
private final void treeifyBin(Node<K,V>[] tab, int index) {
Node<K,V> b; int n, sc;
if (tab != null) {
if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
tryPresize(n << 1);//小于MIN_TREEIFY_CAPACITY就只是数组扩容
else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
...链表转红黑树
}
}
}
private final void tryPresize(int size) {
//如果size大于一般MAXIMUM_CAPACITY就直接取MAXIMUM_CAPACITY,
//否则1.5倍size+1,然后向上取最近的2的次方的数
int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY :
tableSizeFor(size + (size >>> 1) + 1);//
int sc;
while ((sc = sizeCtl) >= 0) {//大于0说明没有正在扩容
Node<K,V>[] tab = table; int n;
//table为null说明是从ConcurrentHashMap(Map<? extends K, ? extends V> m)构造方法进来的
if (tab == null || (n = tab.length) == 0) {
n = (sc > c) ? sc : c;
if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
//赋值为-1,待会可以退出出循环,且阻止其他线程进入这
try {
if (table == tab) {
@SuppressWarnings("unchecked")
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = nt;
sc = n - (n >>> 2);//实际是0.75n
}
} finally {
sizeCtl = sc;
}
}
}
else if (c <= sc || n >= MAXIMUM_CAPACITY)//小于阈值或大于最大容量就不在扩容了
break;
else if (tab == table) {
int rs = resizeStamp(n);
if (sc < 0) {//小于0说明已经开始数据迁移了,新的数组肯定不为空
Node<K,V>[] nt;
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);//开始数据迁移
}
//sc还大于0,说明现在才进行数据迁移,而新的数组还没申请
else if (U.compareAndSwapInt(this, SIZECTL, sc,
(rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null);
}
}
}
真正开始数据迁移是在transfer()方法
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
int n = tab.length, stride;
//cpu数量为1就赋值为n,否则赋值为(n >>> 3) / NCPU ,但最小为MIN_TRANSFER_STRIDE
if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)
stride = MIN_TRANSFER_STRIDE; // subdivide range
if (nextTab == null) { //第一个线程开始扩容时,nextTab为null
try {
@SuppressWarnings("unchecked")
//容量为原来的两倍
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
nextTab = nt;
} catch (Throwable ex) { // try to cope with OOME
sizeCtl = Integer.MAX_VALUE;
return;
}
nextTable = nextTab;
transferIndex = n;//从数组末尾开始数据迁移
}
int nextn = nextTab.length;
//用于标记旧数组中某位置已完成数据迁移
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
boolean advance = true;
boolean finishing = false; // to ensure sweep before committing nextTab
for (int i = 0, bound = 0;;) {
Node<K,V> f; int fh;
while (advance) {
int nextIndex, nextBound;
if (--i >= bound || finishing)//一开始-1会小于0
advance = false;//小于界限或已经完成就赋值为false跳出循环
//transferIndex<=0说明所有数据迁移都有其他线程完成或进行中
else if ((nextIndex = transferIndex) <= 0) {
i = -1;
advance = false;
}
//CAS更新transferIndex值
else if (U.compareAndSwapInt
(this, TRANSFERINDEX, nextIndex,
nextBound = (nextIndex > stride ?
nextIndex - stride : 0))) {
bound = nextBound;//赋值迁移数据的界限
i = nextIndex - 1;//赋值迁移数据的开始下标
advance = false;//跳出循环开始迁移
}
}
if (i < 0 || i >= n || i + n >= nextn) {
int sc;
if (finishing) {//数据迁移完成
nextTable = null;//
table = nextTab;
sizeCtl = (n << 1) - (n >>> 1);//0.75n
return;
}
if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
return;//这里大概会筛选出一个线程进行一遍数据迁移检查
finishing = advance = true;
i = n; // 赋值为n,重新检查一遍是否所有数据已经迁移完成
}
}
else if ((f = tabAt(tab, i)) == null)
//原先为null,说明没有数据可迁移,直接cas赋值为fwd
advance = casTabAt(tab, i, null, fwd);
else if ((fh = f.hash) == MOVED)
//已经是ForwardNode,进入下次循环
advance = true; // already processed
else {
synchronized (f) {//锁住f
if (tabAt(tab, i) == f) {//如果不等,说明第i个节点已变成ForwardingNode了
//分成两条链表
//ln是表示原先节点的哈希值&n为0
//hn表示原先节点的哈希值&n为1
Node<K,V> ln, hn;
if (fh >= 0) {//说明是链表
int runBit = fh & n;
Node<K,V> lastRun = f;
for (Node<K,V> p = f.next; p != null; p = p.next) {
int b = p.hash & n;
if (b != runBit) {
runBit = b;
lastRun = p;
}
}
//lastRun节点及其后面的节点的hash&n都是0或都是1
if (runBit == 0) {
ln = lastRun;
hn = null;
}
else {
hn = lastRun;
ln = null;
}
for (Node<K,V> p = f; p != lastRun; p = p.next) {
int ph = p.hash; K pk = p.key; V pv = p.val;
if ((ph & n) == 0)
ln = new Node<K,V>(ph, pk, pv, ln);
else
hn = new Node<K,V>(ph, pk, pv, hn);
}
//设置新数组的第i位元素为ln链表
setTabAt(nextTab, i, ln);
//设置新数组的第i+n位元素为hn链表
setTabAt(nextTab, i + n, hn);
//设置旧数组中第i个元素为ForwardingNode
setTabAt(tab, i, fwd);
advance = true;
}
else if (f instanceof TreeBin) {//红黑树操作
...
}
}
}
}
}
}
2. 删除操作
public V remove(Object key) {
return replaceNode(key, null, null);
}
final V replaceNode(Object key, V value, Object cv) {
int hash = spread(key.hashCode());
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0 ||
(f = tabAt(tab, i = (n - 1) & hash)) == null)
break;//数组为null或数组第(n - 1) & hash下标下的元素为null直接退出
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);//帮忙迁移数据
else {
V oldVal = null;
boolean validated = false;
synchronized (f) {
//多线程原因要判断是否是同个对象,因为可能被其他线程删除、更换了原来的元素
if (tabAt(tab, i) == f) {
if (fh >= 0) {//链表结构
validated = true;//表示真正操作了
for (Node<K,V> e = f, pred = null;;) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
V ev = e.val;
//cv为null或当和原先的值和cv相等才替换
if (cv == null || cv == ev ||
(ev != null && cv.equals(ev))) {
oldVal = ev;
if (value != null)
e.val = value;
else if (pred != null)//断开链表
pred.next = e.next;
else//是链表头,直接把表头赋值为下一个节点
setTabAt(tab, i, e.next);
}
break;
}
pred = e;
if ((e = e.next) == null)
break;//这里就是没有找到要删除的元素
}
}
else if (f instanceof TreeBin) {//红黑树操作
validated = true;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
if ((r = t.root) != null &&
(p = r.findTreeNode(hash, key, null)) != null) {
V pv = p.val;
if (cv == null || cv == pv ||
(pv != null && cv.equals(pv))) {
oldVal = pv;
if (value != null)
p.val = value;
else if (t.removeTreeNode(p))
setTabAt(tab, i, untreeify(t.first));
}
}
}
}
}
if (validated) {//如果真正操作了
if (oldVal != null) {//原先不为null
if (value == null)//而且新赋值为null说明是删除元素
addCount(-1L, -1);//【标记5】减少计数
return oldVal;//返回旧的值
}
break;
}
}
}
return null;
}
3. 查询数据
public V get(Object key) {
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
int h = spread(key.hashCode());
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) {
//第一个元素就是要找的元素
if ((eh = e.hash) == h) {
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
return e.val;
}
else if (eh < 0)//说明不是链表结构,调用不同节点类型的find方法
return (p = e.find(h, key)) != null ? p.val : null;
//到这里说明是链表结构
while ((e = e.next) != null) {
if (e.hash == h &&
((ek = e.key) == key || (ek != null && key.equals(ek))))
return e.val;
}
}
return null;//没有找到元素
}
4. 计数操作
ConcurrentHashMap的计数方式是,先尝试在baseCount(一个int类型)上计数、如果遇到并发就在尝试在CounterCell上计数。而ConcurrentHashMap要拿到当前所有元素个数的时候就是baseCount+每个CounterCell的计数
@sun.misc.Contended static final class CounterCell {
volatile long value;
CounterCell(long x) { value = x; }
}
final long sumCount() {
CounterCell[] as = counterCells; CounterCell a;
long sum = baseCount;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
//sum=baseCount + counterCells[0..n].value
return sum;
}
文中的【标记5】处是进行计数操作,代码如下,其中参数x表示要增加的计数(正负都有可能),check大于0表示要检查是否达到阈值扩容
private final void addCount(long x, int check) {
CounterCell[] as; long b, s;
if ((as = counterCells) != null ||
!U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
//当counterCells为null或CAS设置baseCount的值失败时,进入下面
CounterCell a; long v; int m;
boolean uncontended = true;
//uncontended为false条件:当counterCells不为null,而且指定下标的计数器不为null,然后cas更新计数器值失败
if (as == null || (m = as.length - 1) < 0 ||
(a = as[ThreadLocalRandom.getProbe() & m]) == null ||
!(uncontended =
U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
//ThreadLocalRandom.getProbe() & m:定位要用哪个计数器
//如果需要用到的计数器为null或没有累加成功就进入这里
//【标记6】全力以赴计数操作
fullAddCount(x, uncontended);
return;
}
if (check <= 1)
return;
s = sumCount();//计算一下容量,为下面如果check>=0时,用其来判断是否要扩容
}
if (check >= 0) {//check大于等于0才检查是否要扩容
Node<K,V>[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n);
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();//再次计算容量,看是否继续扩容
}
}
}
【标记6】处,当未能直接在baseCount上计数,且不能成功在CounterCell[]数组的指定下标计数器上计数,就会进入下面方法
private final void fullAddCount(long x, boolean wasUncontended) {
int h;
if ((h = ThreadLocalRandom.getProbe()) == 0) {
ThreadLocalRandom.localInit(); // 初始化线程的Probe值
h = ThreadLocalRandom.getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
for (;;) {
CounterCell[] as; CounterCell a; int n; long v;
if ((as = counterCells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {//当指定下标的计数器还是null
if (cellsBusy == 0) { // 为0则表示还没其他线程抢到锁
CounterCell r = new CounterCell(x); // Optimistic create
if (cellsBusy == 0 &&
U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {//设置cellsBusy标志位为1
boolean created = false;
try { // Recheck under lock
CounterCell[] rs; int m, j;
if ((rs = counterCells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;//给指定下标元素赋值一个新的CounterCell实例
created = true;
}
} finally {
cellsBusy = 0;
}
if (created)
break;
continue; // Slot is now non-empty
}
}
collide = false;
}
//进入下面说明指定下标的CounterCell不为空了
else if (!wasUncontended) // 调该方法前CAS失败
wasUncontended = true; // Continue after rehash
else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
break;//赋值成功
else if (counterCells != as || n >= NCPU)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 &&
U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {//到这里竞争太厉害,要扩容?
try {
if (counterCells == as) {// Expand table unless stale
//扩容为原来的两倍
CounterCell[] rs = new CounterCell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];//数据迁移
counterCells = rs;
}
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
//重新随机一个probe
h = ThreadLocalRandom.advanceProbe(h);
}
//这里是counterCells数组还没初始化
else if (cellsBusy == 0 && counterCells == as &&
U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
boolean init = false;
try { // Initialize table
if (counterCells == as) {//判断是否还是空
CounterCell[] rs = new CounterCell[2];//一开始只有2个
rs[h & 1] = new CounterCell(x);//根据最低位选一个计数器
counterCells = rs;
init = true;
}
} finally {
cellsBusy = 0;
}
if (init)
break;//直接退出了
}
else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
break; //在baseCount上计数成功
}
}