ConcurrentHashMap --- putVal

首先贴 java 8 中实现的源代码

 1  /** Implementation for put and putIfAbsent */
 2     final V putVal(K key, V value, boolean onlyIfAbsent) {
 3         if (key == null || value == null) throw new NullPointerException();
 4         int hash = spread(key.hashCode());
 5         int binCount = 0;
 6         for (Node<K,V>[] tab = table;;) {
 7             Node<K,V> f; int n, i, fh;
 8             if (tab == null || (n = tab.length) == 0) // 第一次使用时,整个 table 为 null
 9                 tab = initTable();
10             else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
11                 if (casTabAt(tab, i, null,
12                              new Node<K,V>(hash, key, value, null)))
13                     break;                   // no lock when adding to empty bin
14             }
15             else if ((fh = f.hash) == MOVED)    // 当节点的 hash 值为 -1 时,代表这个节点为 ForwardingNode, 其后续节点需要转移
16                 tab = helpTransfer(tab, f);
17             else {
18                 V oldVal = null;
19                 synchronized (f) {
20                     if (tabAt(tab, i) == f) { // 再次获得热区代码执行权后,首先确保之前记录的第 i 个节点没有变化(即没被迁移走)
21                         if (fh >= 0) { // 确保当前节点的 hash 值代表正常的节点(其他的辅助型节点,比如 ForwardingNode,TreeBin,ReservationNode)
22                             binCount = 1;
23                             for (Node<K,V> e = f;; ++binCount) {
24                                 K ek;
25                                 if (e.hash == hash &&
26                                     ((ek = e.key) == key ||
27                                      (ek != null && key.equals(ek)))) { // 判断目标节点的根据是  spread 后的hash值相同并且(key 的 reference 相同或者 key 相等)
28                                     oldVal = e.val;
29                                     if (!onlyIfAbsent)
30                                         e.val = value;
31                                     break;
32                                 }
33                                 Node<K,V> pred = e;
34                                 if ((e = e.next) == null) { // 如果到达当前链表的尾节点,则 append 新的元素
35                                     pred.next = new Node<K,V>(hash, key,
36                                                               value, null);
37                                     break;
38                                 }
39                             }
40                         }
41                         else if (f instanceof TreeBin) { // 当 fh 小于 0,且为 -2 时,此时元素类型为 TreeBin
42                             Node<K,V> p;
43                             binCount = 2;
44                             if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
45                                                            value)) != null) {
46                                 oldVal = p.val;
47                                 if (!onlyIfAbsent)
48                                     p.val = value;
49                             }
50                         }
51                     }
52                 }
53                 if (binCount != 0) {
54                     if (binCount >= TREEIFY_THRESHOLD) // 当插入元素后,单个 slot 的链表的节点数目大于等于 8 时,进行红黑树化这个 slot
55                         treeifyBin(tab, i);
56                     if (oldVal != null)
57                         return oldVal;
58                     break;
59                 }
60             }
61         }
62         addCount(1L, binCount);
63         return null;
64     }
View Code

 

a

猜你喜欢

转载自www.cnblogs.com/neocxf/p/12581015.html