1 /** 2 key:键值 3 value:值 4 onlyIfAbsent:true:如果key存在的情况下,不更新值;Flase:如果key存在的情况下,替换old value 5 **/ 6 final V putVal(K key, V value, boolean onlyIfAbsent) { 7 //不允许key或value为空 8 if (key == null || value == null) throw new NullPointerException(); 9 //在key的hascode值上重新计算key的hash值10 //【(key.hashCode() ^ (key.hashCode() >>> 16)) & 0x7fffffff;】11 int hash = spread(key.hashCode());12 int binCount = 0;13 //CAS锁14 for (Node[] tab = table;;) {15 Node f; int n, i, fh;16 /**17 初始化18 根据hash确认key的Node位置,当node为空时则CAS尝试写入,写入成功流程结束,否则进行下一次尝试19 **/ 20 if (tab == null || (n = tab.length) == 0)21 tab = initTable();22 else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {23 if (casTabAt(tab, i, null,24 new Node (hash, key, value, null)))25 break; // no lock when adding to empty bin26 }27 /**28 static final int MOVED = -1;29 如果当前位置的 hashcode == MOVED == -1, map 正在扩容,其他线程帮助扩容,也就是多线程扩容。30 **/31 else if ((fh = f.hash) == MOVED)32 tab = helpTransfer(tab, f);33 else {34 /**35 利用 synchronized 锁写入数据36 fh〉0 说明这个节点是一个链表的节点不是树的节点。37 如果是红黑树,照树的方式插入值 38 **/39 V oldVal = null;40 synchronized (f) {41 if (tabAt(tab, i) == f) {42 if (fh >= 0) {43 binCount = 1;44 //遍历链表所有结点,如果找到相同key就更新旧值,否则添加至链表尾45 for (Node 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 pred = e;56 if ((e = e.next) == null) {57 pred.next = new Node (hash, key,58 value, null);59 break;60 }61 }62 }63 else if (f instanceof TreeBin) {64 Node p;65 binCount = 2;66 if ((p = ((TreeBin )f).putTreeVal(hash, key,67 value)) != null) {68 oldVal = p.val;69 if (!onlyIfAbsent)70 p.val = value;71 }72 }73 }74 }75 /**76 当链表长度大于8时,将链表转换为红黑树77 **/78 if (binCount != 0) {79 if (binCount >= TREEIFY_THRESHOLD)80 treeifyBin(tab, i);81 if (oldVal != null)82 return oldVal;83 break;84 }85 }86 }87 //如果是新增元素,将当前ConcurrentHashMap的元素数量+188 addCount(1L, binCount);89 return null;90 }