一 特性

  • 在jdk7之中是使用分段锁来保证的(ReentrantLock + Segment + HashEntry) 将HashMap分成多个片段segment,每个段分配一把锁,在8之中使用CAS+Snchronized+Node+红黑树保证的,锁的粒度是Node 首节点
  • jdk1.7的结构
    • image.png
  • jdk1.8的结构
    • image.png

  • 二 属性

    ```java private static final int MAXIMUM_CAPACITY = 1 << 30;

    /* 默认大小 / private static final int DEFAULT_CAPACITY = 16;

// 最大数组长度-转数组使用 static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

  1. /** 最多的并行度
  2. */
  3. private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
  4. /**负载因子
  5. */
  6. private static final float LOAD_FACTOR = 0.75f;
  7. /** 元素超过这个值会转换为红黑树
  8. */
  9. static final int TREEIFY_THRESHOLD = 8;
  10. /** 总元素最小的转换成树的条件 不满足这个只会扩容
  11. */
  12. static final int MIN_TREEIFY_CAPACITY = 64;

// 扩容操作中,单个线程的最小步进 // 数据迁移通过分段迁移,由多线程协调执行,最小段数量为16,则如果长度为16,由一个线程进行扩容 private static final int MIN_TRANSFER_STRIDE = 16;

  1. // 扩容操作使用
  2. private static int RESIZE_STAMP_BITS = 16;
  3. //最大扩容线程数量

private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;

  1. // 扩容操作使用,进行sizeCtl高低位移动,进行扩容线程数判断
  2. private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;

/* 实际存储的数组 / transient volatile Node[] table;

  1. /**
  2. * 扩容的时候使用的下一个数组
  3. */
  4. private transient volatile Node<K,V>[] nextTable;
  5. /** 统计数量
  6. * races. Updated via CAS.
  7. */
  8. private transient volatile long baseCount;
  9. // 用于和负数hash值进行 & 运算,将其转化为正数(绝对值不相等)
  10. static final int HASH_BITS = 0x7fffffff;

// ForwardingNode的hash值,ForwardingNode是一种临时节点,在扩进行中才会出现,并且它不存储实际的数据,ForwardingNode继承自Node,默认hash初始化为-1 static final int MOVED = -1;

// 红黑树的HASH值 static final int TREEBIN = -2;

// ReservationNode的hash值,ReservationNode是一个保留节点,就是个占位符 static final int RESERVED = -3;

/*

  • 非常重要的一个属性,源码中的英文翻译,直译过来是下面的四行文字的意思
  • sizeCtl = -1,表示有线程正在进行真正的初始化操作
  • sizeCtl = -(1 + nThreads),表示有nThreads个线程正在进行扩容操作
  • sizeCtl > 0,表示接下来的真正的初始化操作中使用的容量,或者初始化/扩容完成后的阈值
  • sizeCtl = 0,默认值,此时在真正的初始化操作中使用默认容量 */ private transient volatile int sizeCtl;

    // 扩容任务的起始下标 private transient volatile int transferIndex;

    // CAS自旋锁标志位,用于初始化,或者counterCells扩容时使用 private transient volatile int cellsBusy;

    // 分段计数,记录 private transient volatile CounterCell[] counterCells;

  1. <a name="W7P87"></a>
  2. # 三 重要方法
  3. - tabAt(Node<K,V>[] tab, int i)
  4. - 获取i索引处对象
  5. - casTabAt(Node<K,V>[] tab, int i,Node<K,V> c, Node<K,V> v)
  6. - 把索引 i 处为C 的对象换成V cas方式比较更新
  7. - setTabAt(Node<K,V>[] tab, int i, Node<K,V> v)
  8. - 把 i 索引处对象设置为V
  9. - tableSizeFor
  10. - 给一个传入的数,返回大于给定数字的最小的2的整数次方的数字
  11. <a name="S9VT1"></a>
  12. # 四 添加
  13. ```java
  14. final V putVal(K key, V value, boolean onlyIfAbsent) {
  15. if (key == null || value == null) throw new NullPointerException();
  16. //将hash值进行扰乱 (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16) 这个是hashMap的
  17. // (h ^ (h >>> 16)) & HASH_BITS
  18. int hash = spread(key.hashCode());
  19. int binCount = 0;
  20. for (Node<K,V>[] tab = table;;) {
  21. Node<K,V> f; int n, i, fh;
  22. //这个是初始化阶段
  23. if (tab == null || (n = tab.length) == 0)
  24. //还未初始化则先开始初始化
  25. tab = initTable();
  26. //unSafe直接读取内存 如果指定位置是null 则直接插入
  27. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
  28. if (casTabAt(tab, i, null,
  29. new Node<K,V>(hash, key, value, null)))
  30. break; // no lock when adding to empty bin
  31. }
  32. //扩容阶段
  33. else if ((fh = f.hash) == MOVED)
  34. tab = helpTransfer(tab, f);
  35. else {
  36. V oldVal = null;
  37. //锁住发生hash冲突的第一个节点
  38. synchronized (f) {
  39. //加锁之后再重新检查下 避免其他线程对f进行了更改
  40. if (tabAt(tab, i) == f) {
  41. // 判断头结点的hash值
  42. if (fh >= 0) {
  43. binCount = 1;
  44. //循环链表操作 这里binCount是下边使用进行树化使用
  45. for (Node<K,V> e = f;; ++binCount) {
  46. K ek;
  47. if (e.hash == hash &&
  48. ((ek = e.key) == key ||
  49. (ek != null && key.equals(ek)))) {
  50. oldVal = e.val;
  51. if (!onlyIfAbsent)
  52. e.val = value;
  53. break;
  54. }
  55. Node<K,V> pred = e;
  56. //循环链表
  57. if ((e = e.next) == null) {
  58. pred.next = new Node<K,V>(hash, key,
  59. value, null);
  60. break;
  61. }
  62. }
  63. }
  64. //红黑树插入
  65. else if (f instanceof TreeBin) {
  66. Node<K,V> p;
  67. binCount = 2;
  68. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
  69. value)) != null) {
  70. oldVal = p.val;
  71. if (!onlyIfAbsent)
  72. p.val = value;
  73. }
  74. }
  75. }
  76. }
  77. if (binCount != 0) {
  78. if (binCount >= TREEIFY_THRESHOLD)
  79. treeifyBin(tab, i);
  80. if (oldVal != null)
  81. return oldVal;
  82. break;
  83. }
  84. }
  85. }
  86. addCount(1L, binCount);
  87. return null;
  88. }
  89. // 初始化数组
  90. private final Node<K,V>[] initTable() {
  91. Node<K,V>[] tab; int sc;
  92. while ((tab = table) == null || tab.length == 0) {
  93. if ((sc = sizeCtl) < 0)
  94. Thread.yield(); // lost initialization race; just spin
  95. //java的cas更新方法 读取传入对象在内存中偏移量为SIZECTL 的值与 sc作比较,相等则将-1赋值进入 表示正在初始化 不相等则返回false
  96. // SIZECTL 这个是静态实例已经被初始化为 U.objectFieldOffset(k.getDeclaredField("sizeCtl"));
  97. else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
  98. try {
  99. if ((tab = table) == null || tab.length == 0) {
  100. int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
  101. @SuppressWarnings("unchecked")
  102. Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
  103. table = tab = nt;
  104. // 16 - 4=12
  105. sc = n - (n >>> 2);
  106. }
  107. } finally {
  108. sizeCtl = sc;
  109. }
  110. break;
  111. }
  112. }
  113. return tab;
  114. }
  115. //作用是找到指定位置i的值 使用的是UnSafe直接操作的内存 找到对应位置的偏移量
  116. static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
  117. return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
  118. }
  119. //cas的方式更新进去 先比较在更新
  120. static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
  121. Node<K,V> c, Node<K,V> v) {
  122. return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
  123. }
  124. //当发生hash冲突 check传入的是链的大小
  125. private final void addCount(long x, int check) {
  126. CounterCell[] as; long b, s;
  127. if ((as = counterCells) != null ||
  128. //注意这里会把值累加到 baseCount上 也就是当发生并行访问冲突的时候才会用到下边的代码
  129. !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
  130. CounterCell a; long v; int m;
  131. boolean uncontended = true;
  132. if (as == null || (m = as.length - 1) < 0 ||
  133. (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
  134. !(uncontended =
  135. U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
  136. fullAddCount(x, uncontended);
  137. return;
  138. }
  139. if (check <= 1)
  140. return;
  141. s = sumCount();
  142. }
  143. if (check >= 0) {
  144. Node<K,V>[] tab, nt; int n, sc;
  145. while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
  146. (n = tab.length) < MAXIMUM_CAPACITY) {
  147. int rs = resizeStamp(n);
  148. if (sc < 0) {
  149. if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
  150. sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
  151. transferIndex <= 0)
  152. break;
  153. if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
  154. transfer(tab, nt);
  155. }
  156. else if (U.compareAndSwapInt(this, SIZECTL, sc,
  157. (rs << RESIZE_STAMP_SHIFT) + 2))
  158. transfer(tab, null);
  159. s = sumCount();
  160. }
  161. }
  162. }
  163. // 树化的过程中同样是锁头结点
  164. private final void treeifyBin(Node<K,V>[] tab, int index) {
  165. Node<K,V> b; int n, sc;
  166. if (tab != null) {
  167. if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
  168. tryPresize(n << 1);
  169. else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
  170. synchronized (b) {
  171. if (tabAt(tab, index) == b) {
  172. TreeNode<K,V> hd = null, tl = null;
  173. for (Node<K,V> e = b; e != null; e = e.next) {
  174. TreeNode<K,V> p =
  175. new TreeNode<K,V>(e.hash, e.key, e.val,
  176. null, null);
  177. if ((p.prev = tl) == null)
  178. hd = p;
  179. else
  180. tl.next = p;
  181. tl = p;
  182. }
  183. setTabAt(tab, index, new TreeBin<K,V>(hd));
  184. }
  185. }
  186. }
  187. }
  188. }
  • initTable

    • 综上在经过第一次初始化之后,sizeCtl的值变为12

      五treeifyBin

      1. // 树化的过程中同样是锁头结点
      2. private final void treeifyBin(Node<K,V>[] tab, int index) {
      3. Node<K,V> b; int n, sc;
      4. if (tab != null) {
      5. //必须大于 64才会进行树化 否则会进行扩容
      6. if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
      7. tryPresize(n << 1);
      8. else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
      9. //这里如果插入过程中发生了根节点的变动 这里是将根节点的值进行了改变,而不是对象 所以锁根节点并未失效
      10. synchronized (b) {
      11. if (tabAt(tab, index) == b) {
      12. TreeNode<K,V> hd = null, tl = null;
      13. for (Node<K,V> e = b; e != null; e = e.next) {
      14. TreeNode<K,V> p =
      15. new TreeNode<K,V>(e.hash, e.key, e.val,
      16. null, null);
      17. if ((p.prev = tl) == null)
      18. hd = p;
      19. else
      20. tl.next = p;
      21. tl = p;
      22. }
      23. //红黑树插入 在构造函数之中
      24. setTabAt(tab, index, new TreeBin<K,V>(hd));
      25. }
      26. }
      27. }
      28. }
      29. }

      六 addCount

      ```java // 数量的统计
      private final void addCount(long x, int check) { CounterCell[] as; long b, s; //这里一旦发生过并发冲突之后就不会添加baseCount了 就会直接进入下边的流程 if ((as = counterCells) != null ||

      1. //这里是并发的情况下可能会设置失败 会进入下边的流程
      2. !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
      3. CounterCell a; long v; int m;
      4. boolean uncontended = true;
      5. if (as == null || (m = as.length - 1) < 0 ||
      6. (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
      7. !(uncontended =
      8. U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
      9. fullAddCount(x, uncontended);
      10. return;
      11. }
      12. if (check <= 1)
      13. return;
      14. s = sumCount();

      } if (check >= 0) {

      1. Node<K,V>[] tab, nt; int n, sc;
      2. //这里使用while循环主要是避免并发量高的时候连续进行扩容 所以是这样的
      3. while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
      4. (n = tab.length) < MAXIMUM_CAPACITY) {
      5. int rs = resizeStamp(n);
      6. //当出现并发的时候会进入这里 这里没看懂
      7. if (sc < 0) {
      8. if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
      9. sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
      10. transferIndex <= 0)
      11. break;
      12. if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
      13. transfer(tab, nt);
      14. }
      15. else if (U.compareAndSwapInt(this, SIZECTL, sc,
      16. (rs << RESIZE_STAMP_SHIFT) + 2))
      17. transfer(tab, null);
      18. s = sumCount();
      19. }

      } }

  1. private final void fullAddCount(long x, boolean wasUncontended) {
  2. int h;
  3. //这里是获得当前线程的一个随机值
  4. if ((h = ThreadLocalRandom.getProbe()) == 0) {
  5. ThreadLocalRandom.localInit(); // force initialization
  6. h = ThreadLocalRandom.getProbe();
  7. wasUncontended = true;
  8. }
  9. boolean collide = false; // True if last slot nonempty
  10. for (;;) {
  11. CounterCell[] as; CounterCell a; int n; long v;
  12. if ((as = counterCells) != null && (n = as.length) > 0) {
  13. //这里对应位置 CounterCell 的值为null 则新创建
  14. if ((a = as[(n - 1) & h]) == null) {
  15. //这里使用 cellsBusy 锁避免并发问题 先判断能否访问,不能的话会回到for循环的开始继续执行
  16. if (cellsBusy == 0) { // Try to attach new Cell
  17. CounterCell r = new CounterCell(x); // Optimistic create
  18. if (cellsBusy == 0 &&
  19. //锁住 自旋锁
  20. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
  21. boolean created = false;
  22. try { // Recheck under lock
  23. CounterCell[] rs; int m, j;
  24. if ((rs = counterCells) != null &&
  25. (m = rs.length) > 0 &&
  26. rs[j = (m - 1) & h] == null) {
  27. //将值赋值进去
  28. rs[j] = r;
  29. created = true;
  30. }
  31. } finally {
  32. cellsBusy = 0;
  33. }
  34. if (created)
  35. break;
  36. continue; // Slot is now non-empty
  37. }
  38. }
  39. collide = false;
  40. }
  41. //这里判断如果不进行累加 则直接在原来的CounterCell 上CAS的方式更新对应的值
  42. else if (!wasUncontended) // CAS already known to fail
  43. wasUncontended = true; // Continue after rehash
  44. else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
  45. break;
  46. //下边的代码是如果当前 CounterCell超过NCPU数量 则会进行扩容 扩容为两倍
  47. else if (counterCells != as || n >= NCPU)
  48. collide = false; // At max size or stale
  49. else if (!collide)
  50. collide = true;
  51. else if (cellsBusy == 0 &&
  52. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
  53. try {
  54. if (counterCells == as) {// Expand table unless stale
  55. //具体扩容操作并赋值进入
  56. CounterCell[] rs = new CounterCell[n << 1];
  57. for (int i = 0; i < n; ++i)
  58. rs[i] = as[i];
  59. counterCells = rs;
  60. }
  61. } finally {
  62. cellsBusy = 0;
  63. }
  64. collide = false;
  65. continue; // Retry with expanded table
  66. }
  67. h = ThreadLocalRandom.advanceProbe(h);
  68. }
  69. // 这里是初始化 counterCells的过程 默认长度是2 cellsBusy 是控制并行访问的
  70. else if (cellsBusy == 0 && counterCells == as &&
  71. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
  72. boolean init = false;
  73. try { // Initialize table
  74. if (counterCells == as) {
  75. CounterCell[] rs = new CounterCell[2];
  76. //这里会把数量存储到 CounterCell中
  77. rs[h & 1] = new CounterCell(x);
  78. counterCells = rs;
  79. init = true;
  80. }
  81. } finally {
  82. cellsBusy = 0;
  83. }
  84. if (init)
  85. break;
  86. }
  87. else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
  88. break; // Fall back on using base
  89. }
  90. }
  1. 对应的结构如下所示<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1253306/1633361972565-937a54bd-5107-46b7-b386-a4c2a96066ef.png#clientId=uaafdf15a-41f6-4&from=paste&height=201&id=u47f13058&margin=%5Bobject%20Object%5D&name=image.png&originHeight=201&originWidth=675&originalType=binary&ratio=1&size=11407&status=done&style=none&taskId=ubefd6d74-dacf-488d-8c0f-6cb6c83beee&width=675)
  2. <a name="QP9qS"></a>
  3. # 七 transfer
  4. ```java
  5. private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
  6. int n = tab.length, stride;
  7. //这里相当于是计算cpu核心数 看最多几个线程同时进行扩容 这里假设计算的结果是2
  8. if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)
  9. stride = MIN_TRANSFER_STRIDE; // subdivide range
  10. // 这里是初始化操作 初始化下一个数组
  11. if (nextTab == null) { // initiating
  12. try {
  13. @SuppressWarnings("unchecked")
  14. Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
  15. nextTab = nt;
  16. } catch (Throwable ex) { // try to cope with OOME
  17. sizeCtl = Integer.MAX_VALUE;
  18. return;
  19. }
  20. nextTable = nextTab;
  21. transferIndex = n;
  22. }
  23. int nextn = nextTab.length;
  24. //正在扩容的节点会被赋值 fwd
  25. ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
  26. boolean advance = true;
  27. boolean finishing = false; // to ensure sweep before committing nextTab
  28. //bound的作用相当于为每个线程分区,扩容是按照分区进行的
  29. for (int i = 0, bound = 0;;) {
  30. Node<K,V> f; int fh;
  31. //这里while循环的作用主要是找到当前线程可扩容的区域
  32. while (advance) {
  33. int nextIndex, nextBound;
  34. if (--i >= bound || finishing)
  35. advance = false;
  36. else if ((nextIndex = transferIndex) <= 0) {
  37. i = -1;
  38. advance = false;
  39. }
  40. //当另一个线程也来找可扩容的区域的时候 区域的划分是使用 TRANSFERINDEX 来进行控制的
  41. else if (U.compareAndSwapInt(this, TRANSFERINDEX, nextIndex,nextBound = (nextIndex > stride ?nextIndex - stride : 0))) {
  42. bound = nextBound;
  43. i = nextIndex - 1;
  44. advance = false;
  45. }
  46. }
  47. //这里代表当前线程没有找到可扩容的区域 代表已经扩容完成
  48. if (i < 0 || i >= n || i + n >= nextn) {
  49. int sc;
  50. if (finishing) {
  51. nextTable = null;
  52. table = nextTab;
  53. sizeCtl = (n << 1) - (n >>> 1);
  54. return;
  55. }
  56. if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
  57. if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
  58. return;
  59. finishing = advance = true;
  60. i = n; // recheck before commit
  61. }
  62. }
  63. // 如果扩容的节点是null 则直接赋值fwd
  64. else if ((f = tabAt(tab, i)) == null)
  65. advance = casTabAt(tab, i, null, fwd);
  66. else if ((fh = f.hash) == MOVED)
  67. advance = true; // already processed
  68. else {
  69. //扩容的时候锁住当前要扩容的节点
  70. synchronized (f) {
  71. if (tabAt(tab, i) == f) {
  72. Node<K,V> ln, hn;
  73. if (fh >= 0) {
  74. int runBit = fh & n;
  75. Node<K,V> lastRun = f;
  76. for (Node<K,V> p = f.next; p != null; p = p.next) {
  77. int b = p.hash & n;
  78. if (b != runBit) {
  79. runBit = b;
  80. lastRun = p;
  81. }
  82. }
  83. if (runBit == 0) {
  84. ln = lastRun;
  85. hn = null;
  86. }
  87. else {
  88. hn = lastRun;
  89. ln = null;
  90. }
  91. for (Node<K,V> p = f; p != lastRun; p = p.next) {
  92. int ph = p.hash; K pk = p.key; V pv = p.val;
  93. if ((ph & n) == 0)
  94. ln = new Node<K,V>(ph, pk, pv, ln);
  95. else
  96. hn = new Node<K,V>(ph, pk, pv, hn);
  97. }
  98. setTabAt(nextTab, i, ln);
  99. setTabAt(nextTab, i + n, hn);
  100. setTabAt(tab, i, fwd);
  101. advance = true;
  102. }
  103. else if (f instanceof TreeBin) {
  104. TreeBin<K,V> t = (TreeBin<K,V>)f;
  105. TreeNode<K,V> lo = null, loTail = null;
  106. TreeNode<K,V> hi = null, hiTail = null;
  107. int lc = 0, hc = 0;
  108. for (Node<K,V> e = t.first; e != null; e = e.next) {
  109. int h = e.hash;
  110. TreeNode<K,V> p = new TreeNode<K,V>
  111. (h, e.key, e.val, null, null);
  112. if ((h & n) == 0) {
  113. if ((p.prev = loTail) == null)
  114. lo = p;
  115. else
  116. loTail.next = p;
  117. loTail = p;
  118. ++lc;
  119. }
  120. else {
  121. if ((p.prev = hiTail) == null)
  122. hi = p;
  123. else
  124. hiTail.next = p;
  125. hiTail = p;
  126. ++hc;
  127. }
  128. }
  129. ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) :
  130. (hc != 0) ? new TreeBin<K,V>(lo) : t;
  131. hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) :
  132. (lc != 0) ? new TreeBin<K,V>(hi) : t;
  133. setTabAt(nextTab, i, ln);
  134. setTabAt(nextTab, i + n, hn);
  135. setTabAt(tab, i, fwd);
  136. advance = true;
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }

image.png

八 删除

  1. final V replaceNode(Object key, V value, Object cv) {
  2. int hash = spread(key.hashCode());
  3. for (Node<K,V>[] tab = table;;) {
  4. Node<K,V> f; int n, i, fh;
  5. //删除位置是空的直接返回
  6. if (tab == null || (n = tab.length) == 0 ||
  7. (f = tabAt(tab, i = (n - 1) & hash)) == null)
  8. break;
  9. //要删除的节点正在扩容
  10. else if ((fh = f.hash) == MOVED)
  11. tab = helpTransfer(tab, f);
  12. else {
  13. V oldVal = null;
  14. boolean validated = false;
  15. //同样是锁住特定的节点
  16. synchronized (f) {
  17. if (tabAt(tab, i) == f) {
  18. if (fh >= 0) {
  19. validated = true;
  20. for (Node<K,V> e = f, pred = null;;) {
  21. K ek;
  22. if (e.hash == hash &&
  23. ((ek = e.key) == key ||
  24. (ek != null && key.equals(ek)))) {
  25. V ev = e.val;
  26. if (cv == null || cv == ev ||
  27. (ev != null && cv.equals(ev))) {
  28. oldVal = ev;
  29. if (value != null)
  30. e.val = value;
  31. else if (pred != null)
  32. pred.next = e.next;
  33. else
  34. setTabAt(tab, i, e.next);
  35. }
  36. break;
  37. }
  38. pred = e;
  39. if ((e = e.next) == null)
  40. break;
  41. }
  42. }
  43. else if (f instanceof TreeBin) {
  44. validated = true;
  45. TreeBin<K,V> t = (TreeBin<K,V>)f;
  46. TreeNode<K,V> r, p;
  47. if ((r = t.root) != null &&
  48. (p = r.findTreeNode(hash, key, null)) != null) {
  49. V pv = p.val;
  50. if (cv == null || cv == pv ||
  51. (pv != null && cv.equals(pv))) {
  52. oldVal = pv;
  53. if (value != null)
  54. p.val = value;
  55. else if (t.removeTreeNode(p))
  56. setTabAt(tab, i, untreeify(t.first));
  57. }
  58. }
  59. }
  60. }
  61. }
  62. if (validated) {
  63. if (oldVal != null) {
  64. if (value == null)
  65. addCount(-1L, -1);
  66. return oldVal;
  67. }
  68. break;
  69. }
  70. }
  71. }
  72. return null;
  73. }

九 获取

  1. public V get(Object key) {
  2. Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
  3. int h = spread(key.hashCode());
  4. if ((tab = table) != null && (n = tab.length) > 0 &&
  5. (e = tabAt(tab, (n - 1) & h)) != null) {
  6. if ((eh = e.hash) == h) {
  7. if ((ek = e.key) == key || (ek != null && key.equals(ek)))
  8. return e.val;
  9. }
  10. else if (eh < 0)
  11. return (p = e.find(h, key)) != null ? p.val : null;
  12. while ((e = e.next) != null) {
  13. if (e.hash == h &&
  14. ((ek = e.key) == key || (ek != null && key.equals(ek))))
  15. return e.val;
  16. }
  17. }
  18. return null;
  19. }

十 spread

  1. //先保留hash值的高 16位特性,再与int的最大值进行与 相当于或得到int范围内能表示的数字
  2. static final int spread(int h) {
  3. return (h ^ (h >>> 16)) & HASH_BITS;
  4. }
  5. // (n - 1) & hash 实际使用 相当于对n-1取余操作