游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

ConcurrentHashMap1。7版本源码深度解读

  ConcurrentHashMap是concurrent并发包下重要的工具类,它的设计和实现非常的巧妙,它将数据分段,每段数据使用一个AQS锁,从而减小了锁的粒度。1。ConcurrentHashMap的结构
  结构图
  一个ConcurrentHashMap是由多个Segment(段)组成的。Segment类继承了ReentrantLock类,这意味着每个Segment拥有了一个AQS,多个线程的操作落到同一个Segment上时,发生了锁的竞争。ConcurrentHashMap默认有16个Segment,在初始化之后,Segment个数不可修改。
  一个Segment包含了一个HashEntry的数组,每个HashEntry都是一个单向链表,HashEntry的数组可以扩容,扩容后数组的长度为原来的2倍。HashEntry类如下图所示:
  我们看到value和next都是volatile修饰的,这保证了数据的可见性。2。put方法详解publicVput(Kkey,Vvalue){SegmentK,Vs;if(valuenull)thrownewNullPointerException();计算key的hash值inthashhash(key);hash为32位无符号数,segmentShift默认为28,向右移28位,剩下高4位然后和segmentMask(默认值为15)做与运算,结果还是高4位intj(hashsegmentShift)segmentMask;if((s(SegmentK,V)UNSAFE。getObjectnonvolatile;recheck(segments,(jSSHIFT)SBASE))null)inensureSegment对segment〔j〕进行初始化sensureSegment(j);放入到对应的段内returns。put(key,hash,value,false);}
  第一步是根据hash值快速获取到相应的Segment,第二步就是Segment内部的put操作了。finalVput(Kkey,inthash,Vvalue,booleanonlyIfAbsent){获取该segment的独占锁HashEntryK,VnodetryLock()?null:scanAndLockForPut(key,hash,value);VoldValue;try{HashEntryK,V〔〕tabtable;用hash值和(数组长度1)做与运算,得出数组的下标intindex(tab。length1)hash;first是数组该位置处的链表的表头HashEntryK,VfirstentryAt(tab,index);for(HashEntryK,Vefirst;;){判断是不是到了尾部,尾部nullif(e!null){Kk;key相同,值更新if((ke。key)key(e。hashhashkey。equals(k))){oldValuee。value;if(!onlyIfAbsent){e。valuevalue;modCount;}break;}继续下一个节点ee。next;}else{node不为空,则node作为头节点,使用的是头插法if(node!null)node。setNext(first);elsenodenewHashEntryK,V(hash,key,value,first);intccount1;如果超过了该segment的阈值,这个segment需要扩容if(cthresholdtab。lengthMAXIMUMCAPACITY)rehash(node);else没有达到阈值,将node放到数组tab的index位置,其实就是将新的节点设置成原链表的表头setEntryAt(tab,index,node);modCount;countc;oldValuenull;break;}}}finally{unlock();}returnoldValue;}
  如何进行扩容:privatevoidrehash(HashEntryK,Vnode){HashEntryK,V〔〕oldTabletable;intoldCapacityoldTable。length;扩容为原来的2倍intnewCapacityoldCapacity1;计算阀值threshold(int)(newCapacityloadFactor);HashEntryK,V〔〕newTable(HashEntryK,V〔〕)newHashEntry〔newCapacity〕;intsizeMasknewCapacity1;循环旧的HashEntry数组for(inti0;ioldCapacity;i){HashEntryK,VeoldTable〔i〕;if(e!null){HashEntryK,Vnexte。next;intidxe。hashsizeMask;该链表上只有一个节点if(nextnull)SinglenodeonlistnewTable〔idx〕e;else{ReuseconsecutivesequenceatsameslotHashEntryK,VlastRune;intlastIdxidx;for(HashEntryK,Vlastnext;last!null;lastlast。next){计算在新数组中的下标intklast。hashsizeMask;当前节点的下标和上一个节点的下标不一致时,修改最终节点值注意如果后面的节点和前面的节点下标一致,那么后面的节点保持原有的顺序,直接带到新tab〔k〕的链表中if(k!lastIdx){lastIdxk;lastRunlast;}}采用头插法,最后一个节点作为头节点newTable〔lastIdx〕lastRun;重新计算节点在数组中的位置,采用头插法插入到链表for(HashEntryK,Vpe;p!lastRun;pp。next){Vvp。value;inthp。hash;intkhsizeMask;HashEntryK,VnnewTable〔k〕;newTable〔k〕newHashEntryK,V(h,p。key,v,n);}}}}添加新节点intnodeIndexnode。hashsizeMask;addthenewnodenode。setNext(newTable〔nodeIndex〕);newTable〔nodeIndex〕node;将newTable赋值给该segment的tabletablenewTable;}
  自旋获取aqs锁:privateHashEntryK,VscanAndLockForPut(Kkey,inthash,Vvalue){HashEntryK,VfirstentryForHash(this,hash);HashEntryK,Vefirst;HashEntryK,Vnodenull;intretries1;negativewhilelocatingnode如果尝试加锁失败,那么就对segment〔hash〕对应的链表进行遍历找到需要put的这个entry所在的链表中的位置,这里之所以进行一次遍历找到坑位,主要是为了通过遍历过程将遍历过的entry全部放到CPU高速缓存中,这样在获取到锁了之后,再次进行定位的时候速度会十分快,这是在线程无法获取到锁前并等待的过程中的一种预热方式。while(!tryLock()){HashEntryK,Vf;torecheckfirstbelow获取锁失败,初始时retries1必然开始先进入第一个ifif(retries0){enull代表两种意思,1。第一种就是遍历链表到了最后,仍然没有发现指定key的entry;2。第二种情况是刚开始时entryForHash(通过hash找到的table中对应位置链表的结点)找到的HashEntry就是空的if(enull){当然这里之所以还需要对nodenull进行判断,是因为有可能在第一次给node赋值完毕后,然后预热准备工作已经搞定,然后进行循环尝试获取锁,在循环次数还未达到264次以前,某一次在条件3判断时发现有其它线程对这个segment进行了修改,那么retries被重置为1,从而再一次进入到1条件内,此时如果再次遍历到链表最后时,因为上一次遍历时已经给node赋值过了,所以这里判断node是否为空,从而避免第二次创建对象给node重复赋值。if(nodenull)speculativelycreatenodenodenewHashEntryK,V(hash,key,value,null);retries0;}elseif(key。equals(e。key))retries0;elseee。next;}elseif(retriesMAXSCANRETRIES){尝试获取锁次数超过设置的最大值,直接进入阻塞等待,这就是所谓的有限制的自旋获取锁,之所以这样是因为如果持有锁的线程要过很久才释放锁,这期间如果一直无限制的自旋其实是对cpu性能有消耗的,这样无限制的自旋是不利的,所以加入最大自旋次数,超过这个次数则进入阻塞状态等待对方释放锁并获取锁lock();break;}遍历过程中,有可能其它线程改变了遍历的链表,这时就需要重新进行遍历了。判断是否初始化了结点并且判断链表头结点是否改变(1。7使用头插法)elseif((retries1)0(fentryForHash(this,hash))!first){efirstf;retraverseifentrychangedretries1;}}returnnode;}
  这个方法用了一个while循环去获取aqs锁,有两种情况需要说明下:
  1。如果尝试的次数超过了最大自旋次数,会进入到aqs的等待队列,避免了cpu的空转。
  2。如果在循环的过程中,其他的线程获取到了锁,并且改变了遍历的链表,那么自旋计数器重置为1,从链表的头节点重新开始遍历。3。get方法publicVget(Objectkey){SegmentK,Vs;manuallyintegrateaccessmethodstoreduceoverheadHashEntryK,V〔〕tab;inthhash(key);longu(((hsegmentShift)segmentMask)SSHIFT)SBASE;if((s(SegmentK,V)UNSAFE。getObjectVolatile(segments,u))!null(tabs。table)!null){for(HashEntryK,Ve(HashEntryK,V)UNSAFE。getObjectVolatile(tab,((long)(((tab。length1)h))TSHIFT)TBASE);e!null;ee。next){Kk;if((ke。key)key(e。hashhkey。equals(k)))returne。value;}}returnnull;}
  get方法并没有加锁,基本思路是:
  1。先定位到所在的segment
  2。定位对应的segment的tab数组内的位置
  3。然后遍历链表元素,如果找到相同的key就返回对应的value4。总结:
  ConcurrentHashMap1。7采用了分而治之的思想,将数据分段,每个段持有一把aqs锁。
  它的写操作都是需要获取锁之后再操作,而读操作不需要获取锁,这也说明它适合读多写少的业务场景。
  线程在获取不到aqs锁的情况下,不会立即进入到等待队列,会进行一定次数的自旋。

妖镍青山的生死时刻巨头狙击中国新能源俄乌激战正酣。很多小伙伴会以为西方会稳一边打一边,注意力都放在了东欧战场上。可是大家还是低估了。另一个战场的激烈程度一点不亚于东欧。而且可能持续时间更长,影响也更大。青山……猝不及防!突然暴涨全国行程卡取消星号标记各旅游平台热门旅行目的地搜索量暴涨6月29日,据工信部网站消息,为坚决落实党中央、国务院关于外防输入、内防反弹总策略和动态清零总方针,支……大量上市!钾是香蕉的20倍,建议中老年春天吃1菜,营养丰富春季乍暖还寒,早晚温差较大,所以不管是普通感冒,还是流感等等呼吸道疾病,都是相对比较高发的时期。尤其是近期大家都比较关注的甲流、和诺如病毒。甚至网上报道,有部分地方的学校因为流……江苏53个村庄入选江苏省特色田园乡村来源:人民网江苏频道人民网南京11月11日电11月10日,第十批次江苏省特色田园乡村名单公布,南京市浦口区盘城街道渡桥社区王家渡等53个村庄达到《江苏省特色田园乡村评价命……女人们,你们要学会好好爱自己女人们,你要好好爱自己最近一段时间,大家的生活似乎有些忙碌,有忙着工作的、有忙着健身的、更有忙着去旅游不过,很多人也在忙碌中学会了一件事情:好好爱自己。……且看且珍惜!最后一次踢世界杯的10大球星,7个前锋中他才30四年一届的世界杯将于11月20日12月18日在卡塔尔举行,开幕式和决赛的时间已定,分别是北京时间11月21日0时和12月18日23时进行。揭幕战是东道主卡塔尔VS厄瓜多尔。这届……女人要是过了40岁,春季千万别错过这几种高级色,优雅又减龄女人身处不同年龄阶段,在穿搭上所要注重的地方也不同。二三十岁的女人更喜欢借助时尚出彩的单品款式来展现自身魅力,但女人过了40岁后,更喜欢用基础款打造高级感。那些日常生活中……10位惊艳大众的香港女演员,年轻时都是一眼万年,一见误终身文闲撰奇侠编辑闲撰奇侠上世纪八九十年代,可以说是香港电影的黄金年代,塑造了许多经典的荧幕形象,也造就了许多至今仍在我们记忆中熠熠发光的巨星。那个时候,即使是剧……高二就担任冬奥火炬手,赵睿的小老乡真了不起2022年2月3日,北京冬奥会火炬在河北张家口阳原泥河湾考古遗址公园传递,一位年仅17岁的高二学生参与其中。他叫李梓睿,出生于黑龙江省鸡西市,长于大庆,目前就读于石家庄二……男人喝蜂王浆会有什么不良后果?4个潜在不良后果不容忽视蜂王浆,一种由工蜂分泌出的乳白色浆状物质,被广泛认为是一种营养丰富的保健品。它富含多种氨基酸、维生素、矿物质、生物活性酶等,对人体具有诸多益处。然而,关于男性食用蜂王浆是否会产……格林库里没有我不行,是他让我赚到1。8亿美元随着NBA球员自由市场的开启,拉斯维加斯夏季联赛如火如荼进行中,金州勇士作为下个赛季的卫冕冠军,所有球员的一举一动都会引起媒体的关注,库里已经打完高尔夫,回归健身房训练,克莱也……净水器十大名牌,直饮净水器十大品牌介绍世界净水器十大名牌,冰尊净水器名列前茅!很多家庭现在都注意到了日常用水安全问题,自来水经过市政处理站输送到千家万户过程中很容易产生二次污染,因此选择一款合适的直饮净水器非常重要……
研究数据AppleMusic在谷歌Play安装量超4000万SensorTower商店数据显示,AppleMusic在全球GooglePlay的预估安装量已经达到4000万次。SensorTower预测,本季度该服务在GooglePla……外媒汇总苹果iPhone9(iPhoneSE2)爆料信息IT之家2月20日消息据IT之家此前报道,种种传闻显示今年三月份苹果将发布全新的iPhone9手机(也有称之为iPhoneSE2),尽管苹果一直保持沉默,但有关这款手机的泄露信……Wedbush富士康复工推迟将对苹果造成冲击IT之家2月11日消息Wedbush分析师DanielIves表示,富士康推迟复工将对系统造成冲击,并进一步扰乱苹果公司的供应链。Ives认为,这种中断对苹果公司造成了打……富士康决定推迟2月10日复工计划,包括郑州iPhone工厂IT之家2月9日消息据日经新闻报道,富士康原本计划在下周一(2月10日)复工,以便于在农历春节假期之后继续生产苹果设备。不过受肆虐的新型冠状病毒的影响,富士康取消了复工计划。……地震预警iOS版2019。0。0发布电波跑赢地震波,适配苹果感谢IT之家网友风陵渡客的线索投递!IT之家10月24日消息昨日,地震预警2019。0。0版本上线苹果AppStore,新版本优化了iOS预警信息推送与登录注册功能,并补……梅西不排除参加2026年世界杯,廉颇老矣,尚能饭否?莱昂内尔梅西不排除代表阿根廷参加2026年世界杯的可能性,但他承认,年龄会让参加比赛变得困难。在下一届世界杯期间将年满39岁的梅西去年曾表示,2022年卡塔尔世界杯将是他……电子科技大Angew在BiOBr基底生长应力BiMOF实现高电子科技大学向全军等报道通过修饰在BiOBr基底表面的BiMOF能够作为一种可操作的平台。这种修饰在BiOBr表面的BiMOF能够进行具有特定位点控制应力从而调节CO2光催化转……分析师苹果AirPods今年销售额达60亿美元,明年或将更高伯恩斯坦(Bernstein)的托尼萨克纳吉(ToniSacconaghi)表示,苹果AirPods的销售额今年几乎翻了一番,达到60亿美元,明年应该会有新的飞跃。这位分……广达回应退出AppleWatch组装业务赚钱就做,赚钱最重要新浪科技讯11月14日上午消息,据台湾地区《经济日报》报道,市场盛传广达为了获利问题,将退出AppleWatch组装业务。对此,广达董事长林百里强调,赚钱的就做,赚钱最重要,如……张一山,终为自己的放荡付出了代价阅读此文之前,麻烦您点击一下关注,既方便您进行讨论和分享,又能给您带来不一样的参与感,感谢您的支持文章以宁编辑酒馆茶社前言我想把这玩意染成绿的这就是当年……苹果公司开盘报163。22美元,大涨5。52IT之家1月30日消息苹果发布业绩后的第一个交易日,该公司开盘报163。22美元,大涨5。52。苹果今天发布2019财年第一财季(即2018自然年第四季度)业绩,业绩显示……华尔街多家投行下调苹果目标价北京时间3日消息,苹果周三盘后下调本财年第一季度营收预期,是近20年来首次下调营收预期,受此影响,华尔街多家投行纷纷下调对苹果未来12个月股价的预期。至少四家投行将苹果的……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网