ConcurrentHashMap 的 put 方法执行逻辑是什么?
先来看JDK1.7
首先,会尝试获取锁,如果获取失败,利用自旋获取锁;如果自旋重试的次数超过 64 次,则改为阻塞获取锁。
获取到锁后:
将当前 Segment 中的 table 通过 key 的 hashcode 定位到 HashEntry。
遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value。
不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容。
释放 Segment 的锁。
再来看JDK1.8
大致可以分为以下步骤:
根据 key 计算出 hash值。
判断是否需要进行初始化。
定位到 Node,拿到首节点 f,判断首节点 f:
如果为 null ,则通过cas的方式尝试添加。
如果为 f.hash = MOVED = -1 ,说明其他线程在扩容,参与一起扩容。
如果都不满足 ,synchronized 锁住 f 节点,判断是链表还是红黑树,遍历插入。
当在链表长度达到8的时候,数组扩容或者将链表转换为红黑树。



