ConcurrentHashMap基于分段锁+CAS保证线程安全,分段锁基于synchronized

Put方法
final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();//计算 hash 值int hash = spread(key.hashCode());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();//计算hash 值对应的数组下标,如果为null,则通过cas来赋值//如果赋值成功,则退出自旋else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))break; // no lock when adding to empty bin}//如果数组当前位置的元素的hash值等于MOVED,表示正在进行扩容,当前线程也进行扩容else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else {//到这里就是,f 是该位置的头结点,而且不为空V oldVal = null;synchronized (f) {//锁住该node(该node就是该坐标位置的第一个node)if (tabAt(tab, i) == f) {// 头结点的 hash 值大于 0,说明是链表if (fh >= 0) {//记录链表的长度binCount = 1;for (Node<K,V> e = f;; ++binCount) {K ek;//key相等,判断是否要进行值覆盖if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;if (!onlyIfAbsent)e.val = value;break;}//了链表的最尾,将这个新值放到链表的最后面(尾插法)Node<K,V> pred = e;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) {// 判断是否要将链表转换为红黑树//数组的长大于等于64,而且链表长度大于等于8,会进行树化//否则进行数组扩容if (binCount >= TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;}
