精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深入淺出ConcurrentHashMap內部實現

開發 前端
ConcurrentHashMap可以說是并發設計的典范,在JDK8中,ConcurrentHashMap可以說是再一次脫胎換骨,全新的架構和實現帶來了飛一般的體驗(JDK7中的ConcurrentHashMap還是采用比較骨板的segment實現的),細細品讀,還是有不少的收獲。

ConcurrentHashMap可以說是目前使用最多的并發數據結構之一,作為如此核心的基本組件,不僅僅要滿足我們功能的需求,更要滿足性能的需求。而實現一個高性能的線程安全的HashMap也絕非易事。

ConcurrentHashMap作為JDK8的內部實現,一個成功的典范,有著諸多可以讓我們學習和致敬的地方。

我全局在項目中搜索這個類的時候,發現大量項目代碼和源碼都用到了,為什么他會這么吃香呢?到底是道德的....呸。

下面我們就來扒一扒,ConcurrentHashMap的內部實現,來體會一下它的精妙之處吧!

ConcurrentHashMap的內部數據結構

在JDK8中, ConcurrentHashMap的內部實現發生了天翻地覆的變化。這里依據JDK8,來介紹一下ConcurrentHashMap的內部實現。

從靜態數據結構上說,ConcurrentHashMap包含以下內容:

int sizeCtl

這是一個多功能的字段,可以用來記錄參與Map擴展的線程數量,也用來記錄新的table的擴容閾值

CounterCell[] counterCells

用來記錄元素的個數,這是一個數組,使用數組來記錄,是因為避免多線程競爭時,可能產生的沖突。使用了數組,那么多個線程同時修改數量時,極有可能實際操作數組中不同的單元,從而減少競爭。

Node<K,V>[] table

實際存放Map內容的地方,一個map實際上就是一個Node數組,每個Node里包含了key和value的信息。

Node<K,V>[] nextTable

當table需要擴充時,會把新的數據填充到nextTable中,也就是說nextTable是擴充后的Map。

以上就是ConcurrentHashMap的核心元素,其中最值得注意的便是Node,Node并非想象中如此簡單,下面的圖展示了Node的類族結構:

可以看到,在Map中的Node并非簡單的Node對象,實際上,它有可能是Node對象,也有可能是一個Treebin或者ForwardingNode。

那什么時候是Node,什么時候是TreeBin,什么時候又是一個ForwardingNode呢?

其實在絕大部分場景中,使用的依然是Node,從Node數據結構中,不難看出,Node其實是一個鏈表,也就是說,一個正常的Map可能是長這樣的:

上圖中,綠色部分表示Node數組,里面的元素是Node,也就是鏈表的頭部,當兩個元素在數據中的位置發生沖突時,就將它們通過鏈表的形式,放在一個槽位中。

當數組槽位對應的是一個鏈表時,在一個鏈表中查找key只能使用簡單的遍歷,這在數據不多時,還是可以接受的,當沖突數據比較多少,這種簡單的遍歷就有點慢了。

因此,在具體實現中,當鏈表的長度大于等于8時,會將鏈表樹狀化,也就是變成一顆紅黑樹。如下圖所示,其中一個槽位就變成了一顆樹,這就是TreeBin(在TreeBin中使用TreeNode構造整科樹)。

 

當數組容量快滿時,即超過75%的容量時,數組還需要進行擴容,在擴容過程中,如果老的數組已經完成了復制,那么就會將老數組中的元素使用ForwardingNode對象替代,表示當前槽位的數據已經處理了,不需要再處理了,這樣,當有多個線程同時參與擴容時,就不會沖突。

put()方法的實現

現在來看一下作為一個HashMap最為重要的方法put():

  • public V put(K key, V value)

它負責將給定的key和value對存入HashMap,它的工作主要有以下幾個步驟:

  1. 如果沒有初始化數組,則嘗試初始化數組
  2. 如果當前正在擴容,則參與幫助擴容(調用helpTransfer()方法)
  3. 將給定的key,value 放入對應的槽位
  4. 統計元素總數
  5. 觸發擴容操作

根據以上主要4個步驟,來依次詳細說明一下:

如果沒有初始化數組,則嘗試初始化數組

初始化數據會生成一個Node數組:

  1. Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; 

默認情況下,n為16。同時設置sizeCtl為·n - (n >>> 2); 這意味著sizeCtl為n的75%,表示Map的size,也就是說ConcurrentHashMap的負載因子是0.75。(為了避免沖突,Map的容量是數組的75%,超過這個閾值,就會擴容)

如果當前正在擴容,則參與幫助擴容

  1. else if ((fh = f.hash) == MOVED) 
  2.     tab = helpTransfer(tab, f); 

如果一個節點的hash是MOVE,則表示這是一個ForwardingNode,也就是當前正在擴容中,為了盡快完成擴容,當前線程就會參與到擴容的工作中,而不是等待擴容操作完成,如此緊密細致的操作,恰恰是ConcurrentHashMap高性能的原因。

而代碼中的f.hash==MOVE語義上等同于f instanceof ForwardingNode,但是使用整數相等的判斷的效率要遠遠高于instanceof,所以,這里也是一處對性能的極限優化。

將給定的key,value 放入對應的槽位

在大部分情況下,應該會走到這一步,也就是將key和value放入數組中。在這個操作中會使用大概如下操作:

  1. Node<K,V> f; 
  2. synchronized (f) { 
  3.      if(所在槽位是一個鏈表) 
  4.          插入鏈表 
  5.      else if(所在槽位是紅黑樹) 
  6.          插入樹 
  7.      if(鏈表長度大于8[TREEIFY_THRESHOLD]) 
  8.          將鏈表樹狀化 

可以看到,這使用了synchronized關鍵字,鎖住了Node對象。由于在絕大部分情況下,不同線程大概率會操作不同的Node,因此這里的競爭應該不會太大。

并且隨著數組規模越來越大,競爭的概率會越來越小,因此ConcurrentHashMap有了極好的并行性。

統計元素總數

為了有一個高性能的size()方法,ConcurrentHashMap使用了單獨的方法來統計元素總數,元素數量統計在CounterCell數組中:

  1. CounterCell[] counterCells; 
  2. @sun.misc.Contended static final class CounterCell { 
  3.     volatile long value; 
  4.     CounterCell(long x) { value = x; } 

CounterCell使用偽共享優化,具有很高的讀寫性能。counterCells中所有的成員的value相加,就是整個Map的大小。這里使用數組,也是為了防止沖突。

如果簡單使用一個變量,那么多線程累加一個計數器時,難免要有競爭,現在分散到一個數組中,這種競爭就小了很多,對并發就更加友好了。

累加的主要邏輯如下:

  1. if (as == null || (m = as.length - 1) < 0 || 
  2.     //不同線程映射到不同的數組元素,防止沖突 
  3.     (a = as[ThreadLocalRandom.getProbe() & m]) == null || 
  4.     //使用CAS直接增加對應的數據 
  5.     !(uncontended = 
  6.       U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) 
  7.     //如果有競爭,在這里會重試,如果競爭嚴重還會將CounterCell[]數組擴容,以減少競爭 

觸發擴容操作

最后,ConcurrentHashMap還會檢查是否需要擴容,它會檢查當前Map的大小是否超過了閾值,如果超過了,還會進行擴容。

ConcurrentHashMap的擴容過程非常巧妙,它并沒有完全打亂當前已有的元素位置,而是在數組擴容2倍后,將一半的元素移動到新的空間中。

所有的元素根據高位是否為1分為low節點和high節點:

  1. //n是數組長度,數組長度是2的冪次方,因此一定是100 1000 10000 100000這種二進制數字 
  2. //這里將low節點串一起, high節點串一起 
  3. if ((ph & n) == 0) 
  4.     ln = new Node<K,V>(ph, pk, pv, ln); 
  5. else 
  6.     hn = new Node<K,V>(ph, pk, pv, hn); 

接著,重新放置這些元素的位置:

  1. //low節點留在當前位置 
  2. setTabAt(nextTab, i, ln); 
  3. //high節點放到擴容后的新位置,新位置距離老位置n 
  4. setTabAt(nextTab, i + n, hn); 
  5. //擴容完成,用ForwardingNode填充 
  6. setTabAt(tab, i, fwd); 

下圖顯示了 從8擴充到16時的可能得一種擴容情況,注意,新的位置總是在老位置的后面n個槽位(n為原數組大小)

這樣做的好處是,每個元素的位置不需要重新計算,進行查找時,由于總是會對n-1(一定是一個類似于1111 11111 111111這樣的二進制數)按位與,因此,high類的節點自然就會出現在+n的位置上。

get()方法的實現

與put()方法相比,get()方法就比較簡單了。步驟如下:

  1. 根據hash值 得到對應的槽位 (n - 1) & h
  2. 如果當前槽位第一個元素key就和請求的一樣,直接返回
  3. 否則調用Node的find()方法查找
  4. 對于ForwardingNode 使用的是 ForwardingNode.find()
  5. 對于紅黑樹 使用的是TreeBin.find()
  6. 對于鏈表型的槽位,依次順序查找對應的key

寫在最后

ConcurrentHashMap可以說是并發設計的典范,在JDK8中,ConcurrentHashMap可以說是再一次脫胎換骨,全新的架構和實現帶來了飛一般的體驗(JDK7中的ConcurrentHashMap還是采用比較骨板的segment實現的),細細品讀,還是有不少的收獲。

他和HashMap的區別,優劣勢對比,這也是常考的考點,所以大家不管是為了了解、工作還是面試,都應該好好的熟悉一下。

多線程系列我會繼續更新,我是敖丙,你知道的越多,你不知道的越多,我們江湖見。

 

責任編輯:姜華 來源: 三太子敖丙
相關推薦

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2023-03-20 09:48:23

ReactJSX

2017-07-02 18:04:53

塊加密算法AES算法

2019-01-07 15:29:07

HadoopYarn架構調度器

2021-07-20 15:20:02

FlatBuffers阿里云Java

2012-05-21 10:06:26

FrameworkCocoa

2022-09-26 09:01:15

語言數據JavaScript

2019-11-11 14:51:19

Java數據結構Properties

2009-11-30 16:46:29

學習Linux

2018-11-09 16:24:25

物聯網云計算云系統

2022-11-09 08:06:15

GreatSQLMGR模式

2012-02-21 13:55:45

JavaScript

2022-10-31 09:00:24

Promise數組參數

2009-11-18 13:30:37

Oracle Sequ

2022-12-02 09:13:28

SeataAT模式

2019-12-04 10:13:58

Kubernetes存儲Docker

2022-01-11 07:52:22

CSS 技巧代碼重構

2025-03-27 09:38:35

2016-10-14 13:53:05

JavascriptDOMWeb
點贊
收藏

51CTO技術棧公眾號

亚洲国产精品传媒在线观看| 亚洲三级影院| 6080亚洲精品一区二区| 中文字幕在线中文| 香蕉视频免费看| 日韩一区欧美二区| 欧美成人精品影院| 亚洲av无码成人精品国产| 成人在线高清| 亚洲一区在线播放| 日韩精品一区二区三区四区五区| 国产免费黄色录像| 亚洲一区欧美二区| 久久亚洲精品毛片| 少妇按摩一区二区三区| 日韩电影精品| 精品免费在线观看| 亚洲欧洲精品在线| 婷婷丁香花五月天| 国产中文字幕精品| 日韩暖暖在线视频| 久久这里只有精品国产| 成人看的羞羞网站| 亚洲第一天堂无码专区| 97超碰成人在线| 多野结衣av一区| 亚洲欧美精品午睡沙发| 欧美日韩亚洲免费| 亚洲男人天堂久久| 极品少妇xxxx偷拍精品少妇| 欧美在线不卡区| 免费在线视频一区二区| 欧美在线电影| 亚洲欧美制服综合另类| 亚洲美女在线播放| 国产精品久久久久久久久久辛辛 | 免费一级黄色录像| 国产精品调教| 91精品视频网| 网站一区二区三区| 神马久久午夜| 亚洲一区二区3| 亚洲五码在线观看视频| 日本在线观看| 国产精品国产三级国产aⅴ中文| 欧美色图亚洲自拍| 视频午夜在线| 99精品在线观看视频| 国产高清在线一区二区| 精品国产伦一区二区三| 国产又粗又猛又爽又黄91精品| 国产精品一香蕉国产线看观看| 午夜影院免费在线观看| 国产日韩欧美一区| 69av在线视频| 国产成人在线免费视频| 日韩视频三区| 69视频在线免费观看| 精品无码久久久久久久久| 亚洲香蕉av| 久久福利视频网| 国产精品国产三级国产传播| 清纯唯美亚洲综合一区| 中文在线不卡视频| 蜜桃av免费观看| 久久国产综合| 久久久精品久久| 深夜福利影院在线观看| 欧美三区视频| 91精品国产色综合久久不卡98| 国产成人在线免费观看视频| 亚洲国产精品第一区二区| 欧美精品久久久久久久久| 九九视频免费观看| 国产日产高清欧美一区二区三区| 136fldh精品导航福利| 国产区一区二区三| 日韩二区三区四区| 91久久精品国产91性色| 超碰福利在线观看| 99视频国产精品| 欧洲精品久久| 国产调教视频在线观看| 亚洲国产欧美在线| 日韩avxxx| 国产激情久久| 欧美成人r级一区二区三区| 国产人妻黑人一区二区三区| 国产乱码精品一区二区三区四区| 中文字幕亚洲图片| 91在线播放观看| av成人激情| 国产精品99蜜臀久久不卡二区| www欧美在线| 男女性色大片免费观看一区二区 | 国产偷人爽久久久久久老妇app| 美女一区二区久久| 99久久综合狠狠综合久久止| 日中文字幕在线| 国产精品久久久久精k8| 国产尤物av一区二区三区| 精品国产第一福利网站| 欧美精品v国产精品v日韩精品| 免费观看一区二区三区| 精品久久久亚洲| 欧美激情精品久久久久久黑人| 欧美三日本三级少妇99| 麻豆久久久久久| 国产精品日韩一区二区三区| 国产小视频福利在线| 亚洲精品成人悠悠色影视| 那种视频在线观看| 日韩欧美另类中文字幕| 亚洲天堂色网站| 免费在线视频观看| 美女视频黄a大片欧美| 国内外成人免费视频| 快射av在线播放一区| 日韩欧美国产视频| 中文字幕99页| 亚洲国产精品91| 国产精品扒开腿做| 日韩三级电影网| 亚洲欧美日韩综合aⅴ视频| 久久美女福利视频| 亚洲经典视频| 久久九九国产精品怡红院| 亚洲AV无码成人精品区东京热| 国产suv一区二区三区88区| 亚洲福利av在线| 欧美1级2级| 亚洲国产成人久久综合| 久久99久久久| 国内成+人亚洲+欧美+综合在线| 日韩精品一区二区三区外面| 日本蜜桃在线观看视频| 亚洲成人免费网站| 久久网中文字幕| 国产在线精品一区二区夜色| 亚洲欧洲日韩综合二区| gogo亚洲高清大胆美女人体| 日韩高清欧美高清| 日本免费观看视| 成人动漫一区二区在线| 国产精品无码免费专区午夜| 国产成人视屏| 蜜臀久久99精品久久久无需会员| 中文字幕一区二区三区人妻四季 | 56国语精品自产拍在线观看| 国产性猛交xx乱| 日日噜噜夜夜狠狠视频欧美人| 国内外成人免费视频| www.日本久久| 亚洲黄网在线观看| 日本人妖一区二区| 日本一区二区三区在线视频| 在线观看网站免费入口在线观看国内| 亚洲国产欧美在线成人app| 日韩经典在线观看| 99视频超级精品| 男人添女人下面高潮视频| 欧美黑人巨大videos精品| 97国产在线视频| 日韩av资源| 欧美在线视频你懂得| 五月激情四射婷婷| 国模一区二区三区白浆| 日本免费黄色小视频| 99久久香蕉| 2019av中文字幕| 欧美成人免费| 欧美日韩在线播| 青青操在线视频观看| 国产一区二三区好的| 免费成人进口网站| 99久久免费精品国产72精品九九| 97久久超碰福利国产精品…| 黄色小视频在线免费观看| 欧美在线观看视频在线| 精品少妇一区二区三区密爱| 国产成人免费在线| 亚洲不卡中文字幕无码| 国产探花一区在线观看| 成人a在线观看| 免费在线看电影| 亚洲欧美中文日韩在线| 91久久精品国产91性色69| 夜色激情一区二区| 中日韩精品一区二区三区| 美女尤物国产一区| 成人免费在线网| 精品理论电影在线| 99视频在线播放| 美脚恋feet久草欧美| 深夜福利国产精品| 日本黄视频在线观看| 在线观看免费亚洲| 国产亚洲精品码| 中文一区一区三区高中清不卡| 亚洲综合在线一区二区| 久久一区二区三区超碰国产精品| 宅男av一区二区三区| 日本欧美三级| 91久久嫩草影院一区二区| 激情国产在线| 不卡毛片在线看| 日本免费一区二区三区最新| 欧美一级高清片| 色老头在线视频| 亚洲第一av色| 9999热视频| 国产日本欧美一区二区| 日批在线观看视频| 精品一区免费av| 青青在线视频观看| 国内精品久久久久久久影视蜜臀 | 特黄特色欧美大片| 成人精品网站在线观看| 成人小电影网站| 欧美黄色小视频| 在线观看h片| 亚洲精品综合精品自拍| 午夜精品久久久久久久99| 在线亚洲+欧美+日本专区| 五月婷婷开心网| 亚洲国产日韩a在线播放| 中文字幕观看av| 国产日韩v精品一区二区| 欧美性生交xxxxx| 国产制服丝袜一区| 一道本在线免费视频| 免费精品视频| 国产婷婷一区二区三区| 欧美韩日精品| 国产人妻互换一区二区| 97精品国产福利一区二区三区| 奇米精品在线| 日韩av影院| 久久精品美女| 欧美18xxxx| 国产手机精品在线| 精品国产一区二区三区成人影院 | 日韩中出av| 国产一区二区三区无遮挡| 成功精品影院| 国产精品一区二区你懂得| xxxxxhd亚洲人hd| 亚洲自拍中文字幕| 警花av一区二区三区| 成人深夜直播免费观看| 日本午夜免费一区二区| 国产在线精品播放| 亚洲日韩中文字幕一区| 国产免费一区视频观看免费 | 中文字幕免费高清视频| 99精品视频一区| www.久久国产| 欧美激情综合网| 国产传媒视频在线| 中文字幕一区二区三中文字幕| 日韩亚洲欧美中文字幕| 最新成人av在线| 欧美日韩综合一区二区| 亚洲午夜久久久久久久久电影院| 永久免费看片在线播放| 日韩欧美黄色动漫| 久久久久久亚洲av无码专区| 在线免费观看一区| 国产又大又粗又长| 欧美videos中文字幕| 日批视频免费播放| 亚洲无线码在线一区观看| 日本在线视频站| 久久91精品国产91久久跳| 黄色激情在线播放| 国产精品mp4| 国产精品久久久久久av公交车| 99国产视频在线| 日韩高清一级| 一区二区三区欧美成人| 激情丁香综合| 中文字幕无码不卡免费视频| 久久99精品国产.久久久久久| 中文字幕无人区二| 国产日产亚洲精品系列| 久久久精品视频免费观看| 偷窥少妇高潮呻吟av久久免费| 国产一区免费看| 欧美一区二区美女| 天堂√在线中文官网在线| 色yeye香蕉凹凸一区二区av| 丁香花视频在线观看| 国产成人在线一区| 日韩精品久久久久久久软件91| 久久久久九九九| 99久久亚洲精品蜜臀| a级黄色一级片| 极品少妇xxxx精品少妇偷拍| 国产精品边吃奶边做爽| 国产精品伦一区二区三级视频| 日本亚洲欧美在线| 欧美另类高清zo欧美| 亚洲欧美自偷自拍| 久久精品一偷一偷国产| 综合在线影院| 国产精品二区三区| 欧美电影《轻佻寡妇》| 欧美日韩在线中文| 国产一区二区三区免费观看| 亚洲一级中文字幕| 亚洲午夜影视影院在线观看| 亚洲一区二区激情| 日韩成人中文字幕在线观看| 天堂av最新在线| 国产精品久久网| 欧美色资源站| 91亚洲精品国产| 国内一区二区在线| 亚洲自拍偷拍图| 天天av天天翘天天综合网色鬼国产 | 天美一区二区三区| 国产视频在线观看一区二区三区| 精品亚洲永久免费| 日韩一级片网址| 蜜芽在线免费观看| 国产精品久久久久久久久| 日韩深夜福利| 阿v天堂2017| 成人黄色网址在线观看| 日本少妇高清视频| 欧美日韩国产一二三| 国产片在线观看| 日本免费久久高清视频| 欧美日韩夜夜| 欧美网站免费观看| av中文字幕一区| 国产精品suv一区二区69| 日韩一二三四区| fc2ppv国产精品久久| 成人在线精品视频| 视频在线不卡免费观看| 久热精品在线播放| 欧美国产综合一区二区| 国产精品露脸视频| 在线精品国产成人综合| 欧美电影免费观看高清完整| 久久er99热精品一区二区三区| 日韩图片一区| a级在线观看视频| 欧美特黄级在线| 久久精品国产亚洲a∨麻豆| 2019精品视频| 在线日韩一区| 91视频免费版污| 中文字幕在线观看不卡| 国产精品无码天天爽视频| 久久香蕉国产线看观看av| 精品视频在线一区| 久久视频免费在线| 国产成人在线视频免费播放| 久一视频在线观看| 亚洲高清久久网| 欧美大片高清| 正在播放精油久久| 国产高清精品久久久久| 久久久无码一区二区三区| 精品99一区二区| 天堂中文在线播放| 日韩欧美精品久久| 国产一区二区美女诱惑| 久久久精品国产sm调教| 精品亚洲国产视频| 国产亚洲精彩久久| 日本男女交配视频| 91免费观看国产| 国产精品国产精品国产| 久热精品视频在线免费观看| jizz18欧美18| 天天爽天天爽夜夜爽| 亚洲另类在线一区| 亚洲欧洲国产综合| 国产视频观看一区| 亚洲国产专区| 欧美激情视频二区| 欧美va在线播放| 成人精品电影在线| 日本丰满大乳奶| 久久中文字幕电影| 国产精品视频久久久久久| 91成人在线视频| 久久久久久免费视频| 在线观看国产三级| 7777精品伊人久久久大香线蕉 | 国产成人jvid在线播放| 亚洲第一天堂| 国产精品成人无码免费| 欧美成人bangbros| yiren22亚洲综合| 人妻夜夜添夜夜无码av| 国产精品美女久久福利网站|