最近面试比较多,ConcurrentHashMap问得也比较多。
因此总结了一些关于ConcurrentHashMap的基础知识
Key 和 Value 不能为空
Value 不为空是因为删除和替换走相同的逻辑。
value为空,是删除该节点,需要计算器-1,不为空则是替换该节点的val值。
tab 大小为 pow of 2
Node 类型
存储Node的hash非负数
static final int spread(int h) {
return (h ^ (h >>> 16)) & HASH_BITS;
}
HASH_BITS 的作用,最高bit位变为0.
TreeNode 存储Node
static final int MOVED = -1; // hash for forwarding nodes static final int TREEBIN = -2; // hash for roots of trees static final int RESERVED = -3; // hash for transient reservations
Double-Check
先检测f是否为null,不为空锁f,再次检测 tab[i] 是否等于f 。 场景:frist节点(头节点)被删除,tab[i]就会发生变化。
关键字final与volatile
volatile能解释 为啥读线程遍历单向链表无需加锁,
更新val,保证读线程可见
尾部插入新数据,保证读线程可见。
final int hash; final K key; volatile V val; volatile Node<K,V> next;
计数器 LongAdder
遍历顺序和扩容顺序相反
Simple read write lock
扩容时机,
懒初始化,第一次添加才会new tab[16]
n<64 , 但是链表的数量达到了8,也会触发扩容
达到sizeCtl触发扩容
扩容做法(一条链拆分为两条链)
resizeStamp 应该不会有问的