一图了解ConcurrentHashMap底层原理

1、ConcurrentHashMap底层数据结构是一个数组table
2、table数组上挂着单向链表或红黑树
3、new ConcurrentHashMap();如果没有指定长度的话,默认是16,并且数组长度必须是2的n次幂,若自定义初始化的长度不是2的n次幂,那么在初始化数组时,会吧数组长度设置为大于自定义长度的最近的2的n次幂。(如:自定义长度为7,那么实际初始化数组后的长度为8)
4、底层是使用synchronized作为同步锁,并且锁的粒度是数组的具体索引位(有些人称之为分段锁)。
5、Node节点,hash>0,当hash冲突时,会形成一个单向链表挂在数组上。
6、ForwardindNode,继承至Node,其hash=-1,表示当前索引位的数据已经被迁移到新数组上了
7、ReservationNode,继承至Node,其hash=-3,表示当前索引位被占用了(compute方法)
8、TreenBin,继承至Node,其hash=-2,代表当前索引下挂着一颗红黑树
9、lockState为ConcurrentHashMap底层自己实现的基于cas的读写锁,锁粒度是具体的某颗树。当向红黑树进行增,删操作时,首先会先上sync同步锁,然后自平衡的时候会上lockState写锁,当读红黑树的时候,会上lockState读锁,然后判断此时是否有线程正持有写锁,或是否有线程正在等待获取写锁,若有,则读线程会直接去读双向链表,而不是去读红黑树。
10、TreeNode,hash>0,为红黑树具体节点。TreeBin的root代表红黑树的根节点,first代表双向链表的第一个节点
11、双向链表:构建红黑树时还维护了一个双向链表,其目的为:(1)当并发写读同一颗红黑树的时候,读线程判断到有线程正持有写锁,那么会跑去读取双向链表,避免因为并发写读导致读线程等待或阻塞。(2)当扩容的时候,会去遍历双向链表,重新计算节点hash,根据新的hash判断放在新数组的高位还是地位

1、触发扩容的规则:
1)添加完元素后,若判断到当前容器元素个数达到了扩容的阈值(数组长度*0.75),则会触发扩容
2)添加完元素后,所在的单向链表长度>=8,则会转为红黑树,不过在转红黑树之前会判断数组长度是否小于64,若小于64则会触发扩容
2、table为扩容前的数组,nextTable为扩容中创建的新数组,迁移数据完毕后需要将nextTable赋值给table
3、扩容后的数组是元素组长度的2倍
4、ln,hn分别表示高位和低位的链表(高链,低链)。即,扩容时,会用n&h==0来判断元素应该放在新数组的i位置还是i+n位置。n:元素组长度;h:元素hash值;i:元素所在的原数组索引位;。这样就会出现有些元素会被挂在低位,有些元素会被挂在高位,从而达到打散元素的目的。
5、红黑树扩容时,会遍历双向链表,并且计算n&h==0来判断元素放在低位(lo)还是高位(ho),确定完元素的去处之后,会判断分别判断两个双向链表(lo,ho)的长度是否大于6,若大于6则将还是以一颗红黑树的结构挂在数组上,若<=6的话,则转为单向链表,挂在数组上

  • 涓鍥句簡瑙oncurrentHashMap搴曞眰鍘熺悊
    绛旓細1銆ConcurrentHashMap搴曞眰鏁版嵁缁撴瀯鏄竴涓暟缁則able 2銆乼able鏁扮粍涓婃寕鐫鍗曞悜閾捐〃鎴栫孩榛戞爲 3銆乶ew ConcurrentHashMap();濡傛灉娌℃湁鎸囧畾闀垮害鐨勮瘽锛岄粯璁ゆ槸16锛屽苟涓旀暟缁勯暱搴﹀繀椤绘槸2鐨刵娆″箓锛岃嫢鑷畾涔夊垵濮嬪寲鐨勯暱搴︿笉鏄2鐨刵娆″箓锛岄偅涔堝湪鍒濆鍖栨暟缁勬椂锛屼細鍚ф暟缁勯暱搴﹁缃负澶т簬鑷畾涔夐暱搴︾殑鏈杩戠殑2鐨刵娆″箓銆傦紙濡...
  • java闂,鎺ユ敹閿洏杈撳叆涓涓瓧绗︿覆,鏄剧ず瀛楃涓蹭腑鍚勫瓧绗﹀嚭鐜扮殑娆℃暟,鏄 ...
    绛旓細include<stdio.h>main(){char s[254];char name[4][10]={"UPPER","LOWER","DIGIT","OTHER"};int i,a[4];printf("INPUT A STRING:");gets(s);for(i=0;i<4;i++)a[i]=0;for(i=0;s[i]!='\0';i++){if(s[i]>='A'&&s[i]<='Z')a[0]...
  • 鐢╦ava鎬庝箞鏋勯犱竴涓簩鍙夋爲鍛?
    绛旓細java鏋勯犱簩鍙夋爲锛屽彲浠ラ氳繃閾捐〃鏉ユ瀯閫狅紝濡備笅浠g爜锛歱ublic class BinTree {public final static int MAX=40;BinTree []elements = new BinTree[MAX];//灞傛閬嶅巻鏃朵繚瀛樺悇涓妭鐐 int front;//灞傛閬嶅巻鏃堕槦棣 int rear;//灞傛閬嶅巻鏃堕槦灏緋rivate Object data; //鏁版嵁鍏冩暟private BinTree left,righ...
  • 鍦ㄥ寘鍚玬ain鐨勭被涓繘琛岀殑杩唬闆嗗悎鎿嶄綔涓庡湪鍙︿竴涓繘绋嬩腑杩涜鐨勯泦鍚堝厓绱犲垹...
    绛旓細杩欎釜寮傚父鏄痷til鍖呯殑锛屽簲璇ユ槸鍚屾椂瀵筶ist杩涜鎿嶄綔鎵鍑虹殑闂銆傚湪閬嶅巻鐨勬椂鍊欎笉鍏佽鍒犻櫎銆傝В鍐虫柟娉曪紝瀵硅琚垹闄ょ殑鍏冪礌鍏堢紦瀛橈紝閬嶅巻鐜╀簡鍐嶅垹闄わ細List del= new ArrayList();for(閬嶅巻鍘熼泦鍚坙ist)if(绗﹀悎鍒犻櫎鏉′欢鐨勬煇涓厓绱){ del.add(杩欎釜鍏冪礌);} } list.removeAll(del);
  • java 绾跨▼瀹炵幇涓涓孩缁跨伅闂
    绛旓細import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Signal extends Applet { int width = 200, height = 240;int w = 50, h = 50;int x = (width - w) / 2, y1 = (height - h * 3) / 3, ...
  • 濡備綍璁╃敤鎴疯緭鍏ヤ竴娈典唬鐮,璁╃▼搴忔墽琛
    绛旓細鑴氭湰锛屽湪c++绋嬪簭閲岄潰鍙兘鐢ㄨ剼鏈揪鍒颁綘鐨勮姹備簡 perl鎴栬卲ython閮藉彲浠 濡傛灉浣犺鐢ㄦ埛杈撳叆c++浠g爜骞剁紪璇戞墽琛岋紝閭d綘瑕佷箞鏄啓缂栬瘧鍣紝瑕佷箞灏卞啓涓涓鐢ㄦ搷浣滅郴缁熺殑缂栬瘧鍣ㄧ殑绋嬪簭锛岃繖涓笉鍙兘鐢ㄤ竴涓ゆ浠g爜灏辫В鍐崇殑銆
  • 扩展阅读:coach日本官网入口 ... currently ... currency exchange ... phoenix contact ... concurrent heap ... concurrent 中文翻译 ... 怎么进入cure日本官网 ... concurrent post ... hirose connector ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网