/**
* Base value, used mainly when there is no contention, but also as a
* fallback during table initialization races. Updated via CAS.
*/
volatile long base;
/**
* Table of cells. When non-null, size is a power of 2.
*/
volatile Cell[] cells; // 可以理解为选举活动中的投票箱。如果只有一个箱子,那大家就要排队,队伍可能很长。但如果有多个箱,有多个队伍,分开计票,最后汇总,就能提高效率
/** Number of CPUS, to place bound on table size */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/**
* Spinlock (locked via CAS) used when resizing and/or creating Cells.
*
* 把cellsBusy从0置为1的线程才能对cells进行初始化和扩容,以及往cells里放置元素
*/
volatile int cellsBusy;
/**
* Returns the probe value for the current thread. Duplicated from
* ThreadLocalRandom because of packaging restrictions.
*
* 可以简单理解为获取一个线程安全的随机数
*/
static final int getProbe() {
return UNSAFE.getInt(Thread.currentThread(), PROBE);
}
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; // 从cells中随机选的一个元素
int n; // cells的长度
long v; // 从cells中选出来的元素的初值
if ((as = cells) != null && (n = as.length) > 0) {
// cells已经被初始化
if ((a = as[(n - 1) & h]) == null) {
// 随机选择的数组下标没有元素
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create => 把这一句放到“Recheck under lock”里是不是更好?
if (cellsBusy == 0 && casCellsBusy()) {
boolean created = false;
try { // Recheck under lock
Cell[] rs;
int m, j;
if ((rs = cells) != null && (m = rs.length) > 0
&& rs[j = (m - 1) & h] == null) {
// 往选中的数组下标添加元素
rs[j] = r;
created = true; // 成功地在选中的数组下标里赋值
}
} finally {
cellsBusy = 0;
}
if (created)
break; // 由于已成功地在选中的数组下标里赋值,所以可以跳出循环
continue; // Slot is now non-empty => 其他线程也选中了同样的数组下标,且比当前线程更快,当前线程会重来,而且会重选数组下标
}
}
collide = false; // 当前线程选中的数组下标没有元素,且抢不到cellsBusy
}
// 往下的逻辑:随机选择的数组下标有元素
else if (!wasUncontended) // CAS already known to fail
// wasUncontended为false,当前线程会更新随机数,重选数组下标,这样设计的意图也许是想尽可能选择没有元素的数组下标吧
wasUncontended = true; // Continue after rehash
else if (a.cas(v = a.value,
((fn == null) ? v + x : fn.applyAsLong(v, x))))
break;
// 往下的逻辑:当前线程未能成功地在选中的数组元素(元素不是null)上进行CAS操作
else if (n >= NCPU || cells != as)
// “cells != as”说明其他线程完成了对cells的扩容,让当前线程重来
// “n >= NCPU”说明没必要再扩容。毕竟同时运行的线程数受制于CPU数量,让当前线程重来
collide = false; // At max size or stale
// 往下的逻辑:其他线程未对cells进行扩容,但其实还可以继续对cells进行扩容
else if (!collide)
collide = true; // 当前线程第一次在选中的数组元素(元素不是null)上进行CAS操作失败了
// 往下的逻辑:当前线程连续两次在选中的数组元素(元素不是null)上进行CAS操作都失败了
else if (cellsBusy == 0 && casCellsBusy()) {
// 当前线程对cells进行扩容
try {
if (cells == as) { // Expand table unless stale
// 其他线程未对cells进行扩容
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h); // 更新随机数,用于重选数组下标
}
// cells是null
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
// 只有一个线程能进来初始化cells
boolean init = false;
try { // Initialize table
if (cells == as) {
// 其他线程未对cells进行初始化
Cell[] rs = new Cell[2]; // cell数组初始长度是2
rs[h & 1] = new Cell(x); // 只初始化1个数组元素,并赋值
cells = rs;
init = true;
}
} finally {
cellsBusy = 0;
}
if (init)
break; // 跳出for循环
}
else if (casBase(v = base,
((fn == null) ? v + x : fn.applyAsLong(v, x)))) // 尝试在base上操作
break; // Fall back on using base
}
}
/** * Base value, used mainly when there is no contention, but also as a * fallback during table initialization races. Updated via CAS. */ volatile long base; /** * Table of cells. When non-null, size is a power of 2. */ volatile Cell[] ce..