1. final V putVal(K key, V value, boolean onlyIfAbsent) {
    2. // key和value不能为NULL
    3. if (key == null || value == null) throw new NullPointerException();
    4. // key所对应的hashcode
    5. int hash = spread(key.hashCode());
    6. int binCount = 0;
    7. // 通过自旋的方式来插入数据
    8. for (Node<K,V>[] tab = table;;) {
    9. Node<K,V> f; int n, i, fh;
    10. // 如果数组为空,则初始化
    11. if (tab == null || (n = tab.length) == 0)
    12. tab = initTable();
    13. // 算出数组下标,然后获取数组上对应下标的元素,如果为null,则通过cas来赋值
    14. // 如果赋值成功,则退出自旋,否则是因为数组上当前位置已经被其他线程赋值了,
    15. // 所以失败,所以进入下一次循环后就不会再符合这个判断了
    16. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
    17. if (casTabAt(tab, i, null,
    18. new Node<K,V>(hash, key, value, null)))
    19. break; // no lock when adding to empty bin
    20. }
    21. // 如果数组当前位置的元素的hash值等于MOVED,表示正在进行扩容,当前线程也进行扩容
    22. else if ((fh = f.hash) == MOVED)
    23. tab = helpTransfer(tab, f);
    24. else {
    25. V oldVal = null;
    26. // 对数组当前位置的元素进行加锁
    27. synchronized (f) {
    28. // 加锁后检查一下tab[i]上的元素是否发生了变化,如果发生了变化则直接进入下一次循环
    29. // 如果没有发生变化,则开始插入新key,value
    30. if (tabAt(tab, i) == f) {
    31. // 如果tab[i]的hashcode是大于等于0的,那么就将元素插入到链表尾部
    32. if (fh >= 0) {
    33. binCount = 1; // binCount表示当前链表上节点的个数,不包括新节点
    34. for (Node<K,V> e = f;; ++binCount) {
    35. K ek;
    36. // 遍历链表的过程中比较key是否存在一样的
    37. if (e.hash == hash &&
    38. ((ek = e.key) == key ||
    39. (ek != null && key.equals(ek)))) {
    40. oldVal = e.val;
    41. if (!onlyIfAbsent)
    42. e.val = value;
    43. break;
    44. }
    45. Node<K,V> pred = e;
    46. // 插入到尾节点
    47. if ((e = e.next) == null) {
    48. pred.next = new Node<K,V>(hash, key,
    49. value, null);
    50. break;
    51. }
    52. }
    53. }
    54. // 如果tab[i]是TreeBin类型,表示tab[i]位置是一颗红黑树
    55. else if (f instanceof TreeBin) {
    56. Node<K,V> p;
    57. binCount = 2;
    58. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
    59. value)) != null) {
    60. oldVal = p.val;
    61. if (!onlyIfAbsent)
    62. p.val = value;
    63. }
    64. }
    65. }
    66. }
    67. if (binCount != 0) {
    68. // 在新插入元素的时候,如果不算这个新元素链表上的个数大于等于8了,那么就要进行树化
    69. // 比如binCount为8,那么此时tab[i]上的链表长度为9,因为包括了新元素
    70. if (binCount >= TREEIFY_THRESHOLD)
    71. treeifyBin(tab, i);
    72. // 存在key相同的元素
    73. if (oldVal != null)
    74. return oldVal;
    75. break;
    76. }
    77. }
    78. }
    79. addCount(1L, binCount);
    80. return null;
    81. }
    1. // 初始化数组
    2. // 一个线程在put时如果发现tab是空的,则需要进行初始化
    3. private final Node<K,V>[] initTable() {
    4. Node<K,V>[] tab; int sc;
    5. while ((tab = table) == null || tab.length == 0) {
    6. // sizeCtl默认等于0,如果为-1表示有其他线程正在进行初始化,本线程不竞争CPU
    7. // yield表示放弃CPU,线程重新进入就绪状态,重新竞争CPU,如果竞争不到就等,如果竞争到了又继续循环
    8. if ((sc = sizeCtl) < 0)
    9. Thread.yield(); // lost initialization race; just spin
    10. // 通过cas将sizeCtl改为-1,如果改成功了则进行后续操作
    11. // 如果没有成功,则表示有其他线程在进行初始化或已经把数组初始化好了
    12. else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
    13. try {
    14. // 当前线程将sizeCtl改为-1后,再一次判断数组是否为空
    15. // 会不会存在一个线程进入到此处之后,数组不为空了?
    16. if ((tab = table) == null || tab.length == 0) {
    17. // 如果在构造ConcurrentHashMap时指定了数组初始容量,那么sizeCtl就为初始化容量
    18. int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
    19. @SuppressWarnings("unchecked")
    20. Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
    21. table = tab = nt;
    22. // 如果n为16,那么就是16-4=12
    23. // sc = 3*n/4 = 0.75n, 初始化完成后sizeCtl的数字表示扩容的阈值
    24. sc = n - (n >>> 2);
    25. }
    26. } finally {
    27. // 此时sc为阈值
    28. sizeCtl = sc;
    29. }
    30. break;
    31. }
    32. }
    33. return tab;
    34. }
    1. private final void addCount(long x, int check) {
    2. // 先通过CAS更新baseCount(+1)
    3. // 如果更新失败则通过CAS更新CELLVALUE
    4. // 如果仍然失败则调用fullAddCount
    5. // as是一个CounterCell数组,一个CounterCell对象表示一个计数器,
    6. // 多个线程在添加元素时,手写都会尝试去更新baseCount,那么只有一个线程能更新成功,另外的线程将更新失败
    7. // 那么其他的线程就利用一个CounterCell对象来记一下数
    8. CounterCell[] as; long b, s;
    9. //
    10. if ((as = counterCells) != null ||
    11. !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
    12. // 某个线程更新baseCount失败了
    13. CounterCell a; long v; int m;
    14. boolean uncontended = true;
    15. // 如果CounterCell[]是null
    16. // 或者CounterCell[]不为null的情况下CounterCell[]的长度小于1也就是等于0,
    17. // 或者CounterCell[]长度不为0的情况下随机计算一个CounterCell[]的下标,并判断此下标位置是否为空
    18. // 或者CounterCell[]中的某下标位置不为null的情况下通过cas修改CounterCell中的值失败了
    19. // 才调用fullAddCount方法,然后返回
    20. if (as == null || (m = as.length - 1) < 0 ||
    21. (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
    22. !(uncontended =
    23. U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
    24. fullAddCount(x, uncontended);
    25. return;
    26. }
    27. // 如果修改CELLVALUE成功了,这里的check就是binCount,这里为什么要判断小于等于1
    28. if (check <= 1)
    29. return;
    30. // 如果修改CELLVALUE成功了,则统计ConcurrentHashMap的元素个数
    31. s = sumCount();
    32. }
    33. if (check >= 0) {
    34. Node<K,V>[] tab, nt; int n, sc;
    35. // 如果元素个数大于等于了阈值或-1就自旋扩容
    36. while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
    37. (n = tab.length) < MAXIMUM_CAPACITY) {
    38. // resizeStamp这个方法太难理解,反正就是返回一个数字,比如n=16,rs则=32795
    39. int rs = resizeStamp(n);
    40. // 如果sc小于0,表示已经有其他线程在进行扩容了,sc+1
    41. if (sc < 0) {
    42. // 如果全部元素已经转移完了,或者已经达到了最大并发扩容数限制则breack
    43. if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
    44. sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
    45. transferIndex <= 0)
    46. break;
    47. // 如果没有,则sizeCtl加1,然后进行转移元素
    48. if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
    49. transfer(tab, nt);
    50. }
    51. // 如果sc是大于0的并且如果修改sizeCtl为一个特定的值,比如n=16, rs << RESIZE_STAMP_SHIFT) + 2= -2145714174
    52. else if (U.compareAndSwapInt(this, SIZECTL, sc,
    53. (rs << RESIZE_STAMP_SHIFT) + 2))
    54. // 转移元素,转移完了之后继续进入循环中
    55. transfer(tab, null);
    56. s = sumCount();
    57. }
    58. }
    59. }
    1. private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
    2. int n = tab.length, stride;
    3. // stride表示步长,步长最小为16,如果CPU只有一核,那么步长为n
    4. // 既如果只有一个cpu,那么只有一个线程来进行扩容
    5. // 步长代表一个线程负责转移的桶的个数
    6. if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)
    7. stride = MIN_TRANSFER_STRIDE; // subdivide range
    8. // 新数组初始化,长度为两倍
    9. if (nextTab == null) { // initiating
    10. try {
    11. @SuppressWarnings("unchecked")
    12. Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
    13. nextTab = nt;
    14. } catch (Throwable ex) { // try to cope with OOME
    15. sizeCtl = Integer.MAX_VALUE;
    16. return;
    17. }
    18. nextTable = nextTab;
    19. // 因为是两倍扩容,相当于两个老数组结合成了一个新数组,transferIndex表示第二个小数组的第一个元素的下标
    20. transferIndex = n;
    21. }
    22. // 新数组的长度
    23. int nextn = nextTab.length;
    24. ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
    25. // advance为true时,当前桶是否已经迁移完成,如果迁移完成则开始处理下一个桶
    26. boolean advance = true;
    27. // 是否完成
    28. boolean finishing = false; // to ensure sweep before committing nextTab
    29. // 开始转移一个步长内的元素,i表示
    30. for (int i = 0, bound = 0;;) {
    31. Node<K,V> f; int fh;
    32. while (advance) {
    33. int nextIndex, nextBound;
    34. // i先减1,如果减完之后小于bound,那么继续转移
    35. if (--i >= bound || finishing)
    36. advance = false;
    37. // transferIndex
    38. else if ((nextIndex = transferIndex) <= 0) {
    39. i = -1;
    40. advance = false;
    41. }
    42. // 通过cas来修改TRANSFERINDEX,如果修改成功则对bound和i进行赋值
    43. // 第一循环将进入到这里,来赋值bound和i
    44. // nextIndex就是transferIndex,假设为16,假如步长为4,那么就分为4个组,每组4个桶
    45. // 0-3,4-7,8-11,12-15
    46. // nextBound = 16-4=12
    47. // i=16-1=15
    48. // 所以bound表示一个步长里的最小的下标,i表示一个步长里的最大下标
    49. // TRANSFERINDEX是比较重要的,每个线程在进行元素的转移之前需要确定当前线程从哪个位置开始(从后往前)
    50. // TRANSFERINDEX每次减掉一个步长,所以当下一个线程准备转移元素时就可以从最新的TRANSFERINDEX开始了
    51. // 如果没有修改成功则继续循环
    52. else if (U.compareAndSwapInt
    53. (this, TRANSFERINDEX, nextIndex,
    54. nextBound = (nextIndex > stride ?
    55. nextIndex - stride : 0))) {
    56. bound = nextBound;
    57. i = nextIndex - 1;
    58. advance = false;
    59. }
    60. }
    61. // i表示一个步长里的最大下标, 如果i小于或者大于等于老数组长度,或者下标+老数组长度大于等等新数组长度
    62. if (i < 0 || i >= n || i + n >= nextn) {
    63. int sc;
    64. // 转移完成
    65. if (finishing) {
    66. nextTable = null;
    67. table = nextTab;
    68. // sizeCtl = 1.5n = 2n*0.75
    69. sizeCtl = (n << 1) - (n >>> 1);
    70. return;
    71. }
    72. // 每个线程负责的转移任务结束后利用cas来对sizeCtl减1
    73. if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
    74. // 当前线程负责的任务做完了,同时还有其他线程还在做任务,则回到上层重新申请任务来做
    75. if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
    76. return;
    77. // 当前线程负责的任务做完了,也没有其他线程在做任务了,那么则表示扩容结束了
    78. finishing = advance = true;
    79. i = n; // recheck before commit
    80. }
    81. }
    82. // 从i位置开始转移元素
    83. // 如果老数组的i位置元素为null,则表示该位置上的元素已经被转移完成了,
    84. // 则通过cas设置为ForwardingNode,表示无需转移
    85. else if ((f = tabAt(tab, i)) == null)
    86. advance = casTabAt(tab, i, null, fwd);
    87. // 如果i位置已经是ForwardingNode,则跳过该位置(就是桶)
    88. else if ((fh = f.hash) == MOVED)
    89. advance = true; // already processed
    90. else {
    91. // 加锁,开始转移
    92. synchronized (f) {
    93. // 加锁完了之后再次检查一遍tab[i]是否发生了变化
    94. if (tabAt(tab, i) == f) {
    95. Node<K,V> ln, hn;
    96. // fh大于等于0表示是链表
    97. if (fh >= 0) {
    98. // n是老数组的长度
    99. // 因为n是2的幂次方数,所以runbit只有两种结果:0和n
    100. int runBit = fh & n;
    101. // 遍历链表,lastRun为当前链表上runbit连续相同的一小段的最后一段
    102. Node<K,V> lastRun = f;
    103. for (Node<K,V> p = f.next; p != null; p = p.next) {
    104. int b = p.hash & n;
    105. if (b != runBit) {
    106. runBit = b;
    107. lastRun = p;
    108. }
    109. }
    110. // 如果最后一段的runBit为0,则则该段应该保持在当前位置
    111. // 否则应该设置到i+n位置
    112. if (runBit == 0) {
    113. ln = lastRun;
    114. hn = null;
    115. }
    116. else {
    117. hn = lastRun;
    118. ln = null;
    119. }
    120. //从头节点开始,遍历链表到lastRun结束
    121. for (Node<K,V> p = f; p != lastRun; p = p.next) {
    122. int ph = p.hash; K pk = p.key; V pv = p.val;
    123. // 如果ph & n,则将遍历到的节点插入到ln的前面
    124. // 否则将遍历到的节点插入到hn的前面
    125. if ((ph & n) == 0)
    126. ln = new Node<K,V>(ph, pk, pv, ln);
    127. else
    128. hn = new Node<K,V>(ph, pk, pv, hn);
    129. }
    130. // 将ln链表赋值在新tab的i位置
    131. setTabAt(nextTab, i, ln);
    132. // 将hn链表赋值在新tab的i+n位置
    133. setTabAt(nextTab, i + n, hn);
    134. // 这是老tab的i位置ForwardingNode节点,表示转移完成
    135. setTabAt(tab, i, fwd);
    136. advance = true;
    137. }
    138. else if (f instanceof TreeBin) {
    139. TreeBin<K,V> t = (TreeBin<K,V>)f;
    140. TreeNode<K,V> lo = null, loTail = null;
    141. TreeNode<K,V> hi = null, hiTail = null;
    142. int lc = 0, hc = 0;
    143. for (Node<K,V> e = t.first; e != null; e = e.next) {
    144. int h = e.hash;
    145. TreeNode<K,V> p = new TreeNode<K,V>
    146. (h, e.key, e.val, null, null);
    147. if ((h & n) == 0) {
    148. if ((p.prev = loTail) == null)
    149. lo = p;
    150. else
    151. loTail.next = p;
    152. loTail = p;
    153. ++lc;
    154. }
    155. else {
    156. if ((p.prev = hiTail) == null)
    157. hi = p;
    158. else
    159. hiTail.next = p;
    160. hiTail = p;
    161. ++hc;
    162. }
    163. }
    164. ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) :
    165. (hc != 0) ? new TreeBin<K,V>(lo) : t;
    166. hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) :
    167. (lc != 0) ? new TreeBin<K,V>(hi) : t;
    168. setTabAt(nextTab, i, ln);
    169. setTabAt(nextTab, i + n, hn);
    170. setTabAt(tab, i, fwd);
    171. advance = true;
    172. }
    173. }
    174. }
    175. }
    176. }
    177. }
    1. private final void fullAddCount(long x, boolean wasUncontended) {
    2. int h;
    3. if ((h = ThreadLocalRandom.getProbe()) == 0) {
    4. ThreadLocalRandom.localInit(); // force initialization
    5. h = ThreadLocalRandom.getProbe();
    6. wasUncontended = true;
    7. }
    8. boolean collide = false; // True if last slot nonempty
    9. for (;;) {
    10. CounterCell[] as; CounterCell a; int n; long v;
    11. // 如果counterCells不等于空
    12. if ((as = counterCells) != null && (n = as.length) > 0) {
    13. // h可以理解为当前线程的hashcode,如果对应的counterCells数组下标位置元素当前是空的
    14. // 那么则应该在该位置去生成一个CounterCell对象
    15. if ((a = as[(n - 1) & h]) == null) {
    16. // counterCells如果空闲
    17. if (cellsBusy == 0) { // Try to attach new Cell
    18. // 生成CounterCell对象
    19. CounterCell r = new CounterCell(x); // Optimistic create
    20. // 再次判断counterCells如果空闲,并且cas成功修改cellsBusy为1
    21. if (cellsBusy == 0 &&
    22. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
    23. boolean created = false;
    24. try { // Recheck under lock
    25. CounterCell[] rs; int m, j;
    26. // 如果counterCells对象没有发生变化,那么就将刚刚创建的CounterCell赋值到数组中
    27. if ((rs = counterCells) != null &&
    28. (m = rs.length) > 0 &&
    29. rs[j = (m - 1) & h] == null) {
    30. rs[j] = r;
    31. // 便是CounterCell创建成功
    32. created = true;
    33. }
    34. } finally {
    35. cellsBusy = 0;
    36. }
    37. // 如果CounterCell创建成功,则退出循环,方法执行结束
    38. if (created)
    39. break;
    40. // 如果没有创建成功,则继续循环
    41. continue; // Slot is now non-empty
    42. }
    43. }
    44. // 应该当前位置为空,所以肯定没有发生碰撞
    45. collide = false;
    46. }
    47. // 如果当前位置不为空,则进入以下分支判断
    48. // 如果调用当前方法之前cas失败了,那么先将wasUncontended设置为true,
    49. else if (!wasUncontended) // CAS already known to fail
    50. wasUncontended = true; // Continue after rehash
    51. // 通过cas修改CELLVALUE的值,修改成功则退出循环,修改失败则继续进行分支判断
    52. else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
    53. break;
    54. // counterCells发生了改变,或者当前counterCells数组的大小大于等于CPU核心数,设置collide为false,
    55. // 如果到了这个极限,counterCells不会再进行扩容了
    56. else if (counterCells != as || n >= NCPU)
    57. collide = false; // At max size or stale
    58. // 一旦走到这个分支了,那么就是发生了碰撞了,一个当前这个位置不为空
    59. else if (!collide)
    60. collide = true;
    61. // 当collide为true进入这个分支,表示发生了碰撞会进行扩容
    62. else if (cellsBusy == 0 &&
    63. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
    64. try {
    65. // 对counterCells进行扩容
    66. if (counterCells == as) {// Expand table unless stale
    67. CounterCell[] rs = new CounterCell[n << 1];
    68. for (int i = 0; i < n; ++i)
    69. rs[i] = as[i];
    70. counterCells = rs;
    71. }
    72. } finally {
    73. cellsBusy = 0;
    74. }
    75. collide = false;
    76. continue; // Retry with expanded table
    77. }
    78. // 重新进行hash
    79. h = ThreadLocalRandom.advanceProbe(h);
    80. }
    81. // 如果counterCells等于空的情况下会走下面两个分支
    82. // cellsBusy == 0表示counterCells没有线程在用
    83. // 如果counterCells空闲,并且当前线程所获得counterCells对象没有发生变化
    84. // 先通过CAS将cellsBusy标记改为1,如果修改成功则证明可以操作counterCells了,
    85. // 其他线程暂时不能使用counterCells
    86. else if (cellsBusy == 0 && counterCells == as &&
    87. U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
    88. boolean init = false;
    89. try { // Initialize table
    90. // cellsBusy标记改成后就初始化CounterCell[]
    91. if (counterCells == as) {
    92. CounterCell[] rs = new CounterCell[2];
    93. // 并且把x赋值到CounterCell中完成计数
    94. rs[h & 1] = new CounterCell(x);
    95. counterCells = rs;
    96. init = true;
    97. }
    98. } finally {
    99. cellsBusy = 0;
    100. }
    101. // 如果没有初始化成功,则证明counterCells发生了变化,当前线程修改cellsBusy的过程中,
    102. // 可能其他线程已经把counterCells对象替换掉了
    103. // 如果初始化成功,则退出循环,方法执行结束
    104. if (init)
    105. break;
    106. }
    107. else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
    108. break; // Fall back on using base
    109. }
    110. }

    sizeCtl默认等于0或者用户设置的数组初始容量
    在初始化map的时候会先减1,初始化完成之后就会被设置为扩容的阈值
    当map的元素数量大于等于扩容的阈值之后就会进行循环扩容:
    第一个线程扩容时会把sizeCtl修改为一个很大的负数,然后开始转移元素,如果在这个线程扩容的过程中有其他线程也来帮助扩容了,那么sizeCtl就会加1,如果某个线程扩容结束后就会减1,每个线程减完1之后都判断一下sizeCtl是否不等于之前很大的负数,如果等于则表示当前线程时扩容的最后一个线程了,那么完成map属性的赋值工作,如果不等于并且又没有其他转移任务要做了,那么则退出转移方法,退出之后