初始化容器
private final Node<K, V>[] initTable() { Node<K, V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { // sizeCtl 数组初始化或者扩容的控制位标识 -1 标识正在初始化 -N标识线有现成正在扩容 if ((sc = sizeCtl) < 0) // 判断其他线程是否在操作数组,如果其他线程抢占了操作 让出CPU时间片 Thread.yield(); // lost initialization race; just spin else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { // 通过cas操作将sizeCtl设置成-1 标识当前线程正在初始化 try { if ((tab = table) == null || tab.length == 0) { int n = (sc > 0) ? sc : DEFAULT_CAPACITY; // 没有初始化 数组 sc = -1,默认给数组一个长度 16 @SuppressWarnings("unchecked") Node<K, V>[] nt = (Node<K, V>[]) new Node<?, ?>[n]; // 创建一个长度为16的数组 table = tab = nt; // 将数组赋值给table sc = n - (n >>> 2); // 计算下次扩容的大小,就是0.75 用右移来计算 >>> 2 表示右移两位 10000 -> 100 16->4 所以下次扩容成都为16 - 4 = 12 } } finally { sizeCtl = sc; // 设置sizeCtl为sc } break; } }addCount :添加计数
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)) { // 对baseCount直接+1 如果失败就进方法 CounterCell a; long v; int m; boolean uncontended = true; // 如果counterCells为null 进行初始化 // 如果counterCells的随机元素为空 对counterCells元素值进行增加计数 // 如果counterCells的随机元素不为空 ,尝试通过 cas对改随机元素值进行+1操作 如果失败进入fullAddCount方法 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) // 如果 binCount 长度不超过1个 return; // 如果counterCells的随机元素不为空 ,尝试通过 cas对改随机元素值进行+1操作 如果成功 s = sumCount(); // binCount值加上counterCells所有元素值 } if (check >= 0) { Node<K, V>[] tab, nt; int n, sc; // 如果map元素个数(s)不小于 map扩容数(sizeCtl) 并且容器不为空 容器长度小于1 << 30 while (s >= (long) (sc = sizeCtl) && (tab = table) != null && (n = tab.length) < MAXIMUM_CAPACITY) { int rs = resizeStamp(n); if (sc < 0) { // RESIZE_STAMP_SHIFT = 16 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(); } } }fullAddCount:多个线程同时操作map的时候 计数通过baseCount+counterCells的值来计算
baseCount 单个线程操作时直接+1 在多个线程同时操作的时候 使用CAS方法把baseCount+1会出错,所用会使用counterCells来进行辅助计数
counterCells:初始化是一个长度为2的数组,然后在随机一个元素设置值为1 表示计数增加1 ,
在多个线程同时操作map的时候 会随机取出counterCells一个元素,如果取出的元素为null 就使用CAS方式将值更改为1,如果随机取出的元素值不为空 ,通过CAS修改,如果失败,表示被别的线程修改了,就需要对counterCells进行扩容2倍。
private final void fullAddCount(long x, boolean wasUncontended) { int h; if ((h = ThreadLocalRandom.getProbe()) == 0) { ThreadLocalRandom.localInit(); // force initialization h = ThreadLocalRandom.getProbe(); wasUncontended = true; } boolean collide = false; // True if last slot nonempty for (; ; ) { CounterCell[] as; CounterCell a; int n; long v; // counterCells 已经有值之后 if ((as = counterCells) != null && (n = as.length) > 0) { if ((a = as[(n - 1) & h]) == null) { // 随机取counterCells其中一个元素 如果为null if (cellsBusy == 0) { // 就是一个标志位,如果不是0就是被其他线程在操作 // Try to attach new Cell CounterCell r = new CounterCell(x); // Optimistic create 1 定义一个值为1 if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { // cellsBusy 标准位设置成1 表示被占用 boolean created = false; try { // Recheck under lock CounterCell[] rs; int m, j; // 如果counterCells不为null,但是选取的随机元素为null,将这个随机元素值设置成1 if ((rs = counterCells) != 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 如果counterCells为null,或者选取的随机元素不为null,继续下面的操作 } } collide = false; //collide设置成false } else if (!wasUncontended) // CAS already known to fail 如果cas操作失败 wasUncontended = true; // Continue after rehash else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x)) // 用cas给随机的那个counterCells元素设置 值就是本身的值+1 如果设置成功调处自旋 break; else if (counterCells != as || n >= NCPU) collide = false; // At max size or stale else if (!collide) collide = true; // 这儿是counterCells不为空 而且选择的随机元素值也不为null,同时通过cas去将随机的元素值设置+1失败(失败原因可能是别的线程已经将这个数据值改变) // 所以将counterCells进行扩容 else if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { // cellsBusy 标准位设置成1 表示被占用 try { if (counterCells == as) {// Expand table unless stale CounterCell[] rs = new CounterCell[n << 1]; // 扩容2倍 for (int i = 0; i < n; ++i) rs[i] = as[i]; counterCells = rs; } } finally { cellsBusy = 0; // 标记正在操作的cellsBusy 设置为0 表示没有线程操作 } collide = false; continue; // Retry with expanded table } h = ThreadLocalRandom.advanceProbe(h); // 重新获取扩容之后的随机数 // 最新数据过来 满足条件 对cellsBusy进行赋值为0 counterCells初始化长度为2的数组 其中一个随机元素设置为1 } 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); // 随机设置一个元素值为1 x=1 counterCells = rs; // 将初始化的数组设置给counterCells init = true; } } finally { cellsBusy = 0; // cellsBusy设值为0 } if (init) // 初始化之后跳出自旋 break; } else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x)) // 直接对counterCells进行+1 (在这之前只是对counterCells进行扩容,没有设置值的时候) break; // Fall back on using base } }