ConcurrentHashMap源码分析详解编程语言

本篇是自己对ConcurrentHashMap某些源码的一些分析。

put方法

public V put(K key, V value) {
 
return putVal(key, value, false); 
} 
/** Implementation for put and putIfAbsent */ 
final V putVal(K key, V value, boolean onlyIfAbsent) {
 
//不允许插入null键 
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; K fk; V fv; 
//Node数组为空则进行数组初始化 
if (tab == null || (n = tab.length) == 0) 
tab = initTable(); 
//如果数组对应位置没有值,就进行cas添加,失败就进行break,注意求位置用了与操作 
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
 
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value))) 
break;                   // no lock when adding to empty bin 
} 
//如果此位置元素已经存在,且处于被移动元素状态,就协助扩容 
else if ((fh = f.hash) == MOVED) 
tab = helpTransfer(tab, f); 
//不进入此块。因为put方法中onlyIfAbsent传入为false 
else if (onlyIfAbsent // check first node without acquiring lock 
&& fh == hash 
&& ((fk = f.key) == key || (fk != null && key.equals(fk))) 
&& (fv = f.val) != null) 
return fv; 
//发生hash碰撞,就锁注此位置的链表或红黑树 
else {
 
V oldVal = null; 
synchronized (f) {
 
//如果此位置是 链表 的头结点。 
//f是此位置头结点,i是通过hash求出的元素位置,求法见第一个else if那里的条件 
if (tabAt(tab, i) == f) {
 
if (fh >= 0) {
 
binCount = 1; 
for (Node<K,V> e = f;; ++binCount) {
 
K ek; 
//若存在此节点,就更新value值 
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); 
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; 
} 
} 
//若f是保留节点,就抛出更新异常 
else if (f instanceof ReservationNode) 
throw new IllegalStateException("Recursive update"); 
} 
} 
//若链表长度到达临界值,就转为红黑树 
if (binCount != 0) {
 
if (binCount >= TREEIFY_THRESHOLD) 
treeifyBin(tab, i); 
if (oldVal != null) 
return oldVal; 
break; 
} 
} 
} 
addCount(1L, binCount); 
return null; 
} 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/19387.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论