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/tech/pnotes/19387.html

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

相关推荐

发表回复

登录后才能评论