public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable {
private static final long serialVersionUID = 7249069246763182397L;
//table初始化
private final Node<K,V>[] initTable() {
Node<K,V>[] tab;
int sc;
while ((tab = table) == null || tab.length == 0) {
if ((sc = sizeCtl) < 0)// sizeCtl小于0,则进行线程让步等待
Thread.yield(); // lost initialization race; just spin
else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {// 比较sizeCtl的值与sc是否相等,相等则用-1替换
try {
if ((tab = table) == null || tab.length == 0) {
//根据sizeCtl的值进行设置,如果没有设置szieCtl的值,那么默认生成的table大小为16
int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
@SuppressWarnings("unchecked")
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt;
sc = n - (n >>> 2);// sc为n * 3/4
}
} finally {
sizeCtl = sc;
}
break;
}
}
return tab;
}
//返回table数组中下标为i的结点
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
//ASHIFT是指tab[i]中第i个元素相对于数组第一个元素的偏移量,而ABASE是数组在内存中第一个元素的偏移地址
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
//比较table数组下标为i的结点是否为c,若为c,则用v置换
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
Node<K,V> c, Node<K,V> v) {
return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}
//在扩容时将table表中的结点转移到nextTable中
final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
Node<K,V>[] nextTab;
int sc;
//table不为null & 结点类型是ForwardingNode & 结点的nextTable域不为空
if (tab != null && (f instanceof ForwardingNode) &&
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
int rs = resizeStamp(tab.length);
while (nextTab == nextTable && table == tab &&
(sc = sizeCtl) < 0) {
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || transferIndex <= 0)
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
transfer(tab, nextTab);// 将table的结点转移到nextTab中
break;
}
}
return nextTab;
}
return table;
}
//添加key-value
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
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)//表为null或者长度为0
tab = initTable();//初始化表
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
//table的第i项为空则用新生成的node置换
if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)// 该结点的hash值为MOVED
tab = helpTransfer(tab, f);// 进行结点的转移(在扩容的过程中)
else {
V oldVal = null;
synchronized (f) { //锁定了f,f是链表的第一个元素,则锁住了整个链表
if (tabAt(tab, i) == f) {// 找到table表下标为i的节点并且等于f
if (fh >= 0) { // table表中该结点的hash值>=0
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
//结点hash值相等且key相等,则为同一个key
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;//保存结点旧值
if (!onlyIfAbsent)
e.val = value;//更新结点value值
break;
}
Node<K,V> pred = e;//保存当前结点
//当前结点的后继结点为空,当前结点为最后一个结点
if ((e = e.next) == null) {
//生成新结点,最后一个结点pre的next指向它
pred.next = new Node<K,V>(hash, key,
value, null);
break;//key-value添加成功退出循环
}
}
}
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) {
if (binCount >= TREEIFY_THRESHOLD)// 如果binCount大于等于转化为红黑树的阈值
treeifyBin(tab, i);
if (oldVal != null)
return oldVal;
break;
}
}
}
addCount(1L, binCount);
return null;
}
}
ConcurrentHashMap源码阅读
最新推荐文章于 2025-11-15 04:30:45 发布
本文详细解析了ConcurrentHashMap的内部实现机制,包括初始化过程、添加键值对的方法、以及在扩容时的数据迁移流程。
486

被折叠的 条评论
为什么被折叠?



