ConcurrentHashMap
重要的参数
默认为0,-1表示正在创建table
private transient volatile int sizeCtl; /
HASH_BITS是0x7fffffff,为了消除最高位上的负符号 hash的负在ConcurrentHashMap中有特殊意义表示在扩容或者是树节点
static final int HASH_BITS = 0x7fffffff; static final int spread(int h) { return (h ^ (h >>> 16)) & HASH_BITS; }
在计数的时候,判断counterCells是否有人在修改
/** * Spinlock (locked via CAS) used when resizing and/or creating CounterCells. */ private transient volatile int cellsBusy;
1、Put流程
public V put(K key, V value) { return putVal(key, value, false); } /** Implementation for put and putIfAbsent */ final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); // key 和 value 都不允许为空 int hash = spread(key.hashCode()); // 获取它的hash值 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(); //判断table是否为空,如果为空那么就初始化table else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null))) //如果该位置为null,那么就CAS新增元素 break; // no lock when adding to empty bin } else if ((fh = f.hash) == MOVED) //f.hash == -1,就帮助转移 tab = helpTransfer(tab, f); else { V oldVal = null; synchronized (f) { //定位到的元素不为空,就锁住 if (tabAt(tab, i) == f) { //判断下tab[i]位置的元素没有被修改,f = tabAt(tab, i = (n - 1) & hash) 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)))) { //判断key是否相同 oldVal = e.val; //将原来的value赋值给oldVal if (!onlyIfAbsent) //参数传进来的是false e.val = value; //value覆盖 break; } Node<K,V> pred = e; //如果没有相同的key匹配,就插入到队列的尾部 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) //链表的时候,binCount会递增,判断是否>=8 treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); return null; }
1.1、initTable() : 初始化table,如果CAS修改SIZECTL为-1,成功则开始创建,如果sizeCtl < 0,让出CPU。保证只有一个线程在创建table
/** * Initializes table, using the size recorded in sizeCtl. */ private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { if ((sc = sizeCtl) < 0) //sizeCtl<0时表示正在扩容或者创建数组 Thread.yield(); // lost initialization race; just spin else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { //CAS判断SIZECTL和sc相同SIZECTL赋值-1表示正在初始化,只有一个线程进行初始化其它线程在上个if卡住 try { if ((tab = table) == null || tab.length == 0) { //第一个线程初始化之后,第二个线程还会进来所以需要再次判断一次 int n = (sc > 0) ? sc : DEFAULT_CAPACITY; @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; table = tab = nt; sc = n - (n >>> 2); //0.75 n } } finally { sizeCtl = sc; } break; } } return tab; }
1.2、
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计数的一部分,如果CAS修改BASECOUNT失败,执行下面的逻辑 CounterCell a; long v; int m; boolean uncontended = true; if (as == null || (m = as.length - 1) < 0 || //CounterCell数组为空 (a = as[ThreadLocalRandom.getProbe() & m]) == null || //线程获取一个随机值与数组长度-1进行与操作,获得一个下标,如果数组该下标为null !(uncontended = U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) { //如果不为null,CAS也失败了,就进入fullAddCount fullAddCount(x, uncontended); //计数的实现 return; } if (check <= 1) return; s = sumCount(); } if (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(); } } }
1.3、CounterCell不为空,则通过CounterCell计数。为空则通过BASECOUNT计数。cellsBusy默认为0,为1表示有线程正在操作,线程要操作数组前都会通过CAS修改cellsBusy。CounterCell初始大小为2,当一个线程多次修改未果时,数组发生扩容大小为原来的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; if ((as = counterCells) != null && (n = as.length) > 0) { //如果counterCells不为空 if ((a = as[(n - 1) & h]) == null) { 第一个分支,as[x] == null if (cellsBusy == 0) { // Try to attach new Cell CounterCell r = new CounterCell(x); // Optimistic create if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { //CAS修改标志位 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) { //数组不为空,并且通过线程随机数ThreadLocalRandom.getProbe() 和数组的长度-1进行与运算计算得下标,如果数组该位置为空,添加 rs[j] = r; created = true; } } finally { cellsBusy = 0; //数组标志位改回为0 } if (created) break; continue; // Slot is now non-empty } } collide = false; } else if (!wasUncontended) // CAS already known to fail wasUncontended = true; // Continue after rehash else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x)) // 不为空则CAS操作加 break; else if (counterCells != as || n >= NCPU) 走到这边的条件时tab[x]不为空,CAS操作失败。那么如果数组发生了变化,或者n大于等于可用处理器储量,那么就走这个分支 collide = false; // At max size or stale else if (!collide) //tab[x]不为空,CAS操作失败,数组发生了变化,或者n大于等于可用处理器,将collide改为true 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 } h = ThreadLocalRandom.advanceProbe(h); //每次循环结束都会获取一个新的随机数,我的理解时防止每次在同一个位置添加,万一其他位置都是空闲的,那就不合理 } else if (cellsBusy == 0 && counterCells == as && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { //counterCells为空并且CAS修改CELLSBUSY成功 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)) //保底CAS对BASECOUNT操作 break; // Fall back on using base } }
2、get
public V get(Object key) { Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek; int h = spread(key.hashCode()); //计算hash 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) //树查找 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; }
https://www.cnblogs.com/zerotomax/p/8687425.html