目录
1.Striped64
1.probe
获取当前线程在内存中的PROBE值,类似于线程的哈希值
static final int getProbe() {
return UNSAFE.getInt(Thread.currentThread(), PROBE);
}
public static ThreadLocalRandom current() {
if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
localInit();
return instance;
}
static final void localInit() {
int p = probeGenerator.addAndGet(PROBE_INCREMENT);
int probe = (p == 0) ? 1 : p; // probe值不能为0
long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
Thread t = Thread.currentThread();
UNSAFE.putLong(t, SEED, seed);
UNSAFE.putInt(t, PROBE, probe);
}
static final int advanceProbe(int probe) {
probe ^= probe << 13;
probe ^= probe >>> 17;
probe ^= probe << 5;
UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
return probe;
}
2.NCPU
CPU的核心数,Cells数组的最大长度为大于等于NCPU的最小的2的N次方,比如NCPU为7,则Cells数组最大length为8
static final int NCPU = Runtime.getRuntime().availableProcessors();
3.cells
cell数组,长度永远为2的N次方,初始化后数组容量是2
transient volatile Cell @Nullable [] cells;
4.base
当不存在并发修改时直接CAS更新base值,当CAS修改base失败且cell数组初始化并发竞争时,继续CAS修改一次Base值作为fallback操作
transient volatile long base;
5.cellsBusy
标志底层数组是不是busy状态,busy为1、不busy为0
transient volatile int cellsBusy;
2.sum()
public long sum() {
Cell[] as = cells; Cell a;
long sum = base;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}
3.add()
-
cells为null,尝试CAS修改base成功,直接返回
-
cells为null、尝试CAS修改base失败,或者cells不为null,都是直接进入if代码块
-
如果cells已经完成了初始化,尝试寻址然后CAS修改值,成功后直接返回
-
如果cells已经完成了初始化、且寻址后CAS修改值失败,代表存在竞争,uncontended为false
-
如果cells还没完成了初始化,通过longAccumulate方法进行初始化
-
public void add(long x) {
Cell[] as; long b, v; int m; Cell a;
// cells为null 尝试CAS修改base 成功后返回
if ((as = cells) != null || !casBase(b = base, b + x)) {
// cells不为null 或者CAS修改base失败 进入IF代码块
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null || // 获取当前线程哈希值在Cells上寻址slot
// 若as不为null 且slot上不为null 尝试修改slot上的值
// 若修改失败说明存在并发竞争 uncontended为false
!(uncontended = a.cas(v = a.value, v + x)))
// 核心方法
longAccumulate(x, null, uncontended);
}
}
4.longAccumulate()
-
初始化PROBE
值 -
cells已经完成
了初始化-
cells是空闲状态、且CAS修改状态成功
-
recheck检查成功后,寻址后进行目标Cell对象值修改
-
recheck失败后,直接进行下一次循环
-
-
cells是忙碌状态,如果目前Cell上存在竞争,将wasUncontended由false改为ture
-
cells是忙碌状态,目标Cell上不存在并发竞争,继续尝试CAS修改目标Cell对象值,成功后直接返回
-
cells是忙碌状态,但尝试CAS修改目标Cell对象值失败,判断cells数组有没有扩容到最大容量或者有没有在进行扩容
-
如果扩容到最大容量了、或者正在进行扩容,修改collide为false
-
-
cells是忙碌状态,且collide为false,修改collide为true,准备进行数组扩容
-
如果这个时候cells是空闲状态、且CAS修改状态成功
-
recheck检查成功后,进行cells数组扩容,容量变为之前2倍
-
recheck失败后,直接进行下一次循环
-
-
上面的判断完成后,使用新的散列方法,重新计算一个PROBE值
-
-
cells还没
初始化,准备开始初始化-
初始容量是2
-
-
cells正在
初始化过程中,fallback机制
再去尝试CAS修改base值-
修改成功后直接返回
-
CAS修改base值失败后,继续下一次循环
-
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
// 初始化PROBE值
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current();
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // 是否发生哈希碰撞
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) { // Cells数组已经完成了初始化
if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // cells数组是空闲状态 CAS修改成功后将新建的Cell对象放在cell处
Cell r = new Cell(x);
if (cellsBusy == 0 && casCellsBusy()) {
boolean created = false;
try {
Cell[] rs; int m, j; // rs是cells的引用
if ((rs = cells) != null && // reCheck
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
cellsBusy = 0;
}
if (created) // 创建成功就跳出自旋
break;
continue; // 可能在reCheck的时候由于并发竞争失败了 继续下次循环
}
}
collide = false; // 未哈希碰撞
}
// cells数组是busy状态 wasUncontended为false
// 这个时候修改wasUncontended为true 然后进行下面的else-if判断
else if (!wasUncontended)
wasUncontended = true;
// cells数组是busy状态、wasUncontended为true 继续尝试CAS修改cell上的Cell对象值
// 修改成功结束自旋 否则继续下面的else-if判断
else if (a.cas(v = a.value, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break;
// cells数组是busy状态、wasUncontended为true、尝试CAS修改cell上的Cell失败
// 如果这个时候cells数组已经扩容到了最大值 或者正在进行扩容 则哈希碰撞标志为false 继续下面else-if判断
else if (n >= NCPU || cells != as)
collide = false;
// cells数组是busy状态、wasUncontended为true、尝试CAS修改cell上的Cell失败
// 且cells没有进行扩容操作、或者还没扩容到最大 这个时候修改哈希碰撞标志为true
else if (!collide)
collide = true;
// collide为true、cells数组是空闲状态、且CAS修改为busy状态成功 接着开始cells数组的扩容操作
else if (cellsBusy == 0 && casCellsBusy()) {
try {
if (cells == as) { // reCheck
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
cellsBusy = 0;
}
collide = false; // 扩容完成后 修改collide为false
continue; // reCheck失败 继续下一次循环
}
// 上面一大坨if代码后 用新的散列函数计算一个新的PROBE值
h = advanceProbe(h);
}
else if (cellsBusy == 0 && cells == as && casCellsBusy()) { // cells数组没完成初始化 且是空闲状态
boolean init = false;
try {
if (cells == as) {
Cell[] rs = new Cell[2]; // 初始容量为2
rs[h & 1] = new Cell(x);
cells = rs;
init = true;
}
} finally {
cellsBusy = 0; // 初始化完毕 修改busy状态
}
if (init)
break;
}
// cells数组正在由其他线程初始化、但是还没完成初始化 这里是一个fallback机制 再次尝试CAS修改base值
else if (casBase(v = base, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break;
}
}
5.reset()
public void reset() {
internalReset(0L);
}
final void internalReset(long initialValue) {
Cell[] as = cells;
base = initialValue; // 修改base值
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) { // 修改cells数组值
Cell a = as[i];
if (a != null) a.value = initialValue;
}
}
}