亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

Java并發編程 - 常用容器(ConcurrentHashMap, ConcurrentLinkedQueue)

2019-11-06 06:18:12
字體:
來源:轉載
供稿:網友

ConcurrentHashMap的實現原理與使用

傳統的HashMap不是線程安全的, 所以多線程進行put()get()操作的時候可能會引發問題. 還有一個叫做HashTable的數據結構, 它使用的是synchronized來保證線程安全, 但是效率很低, 因為不能并發讀.

ConcurrentHashMap采用的是鎖分段技術, 將數據分成一段一段存儲, 然后給每一段數據配一把鎖, 當一個線程對某段數據進行寫操作的時候, 其他段的數據也能被其他線程安全訪問(讀寫).

ConcurrentHashMap的結構

一個ConcurrentHashMap包含一個Segment數組;一個Segment里面包含一個HashEntry鏈表.

Segment是一種可重入鎖, 在ConcurrentHashMap中扮演鎖的角色. HashEntry則是實際存儲鍵值對數據的地方. 當對HashEntry的數據進行修改時, 必須首先獲得與它對應的Segment鎖.

ConcurrentHashMap

ConcurrentHashMap的初始化

初始化segments數組

if (concurrencyLevel > MAX_SEGMENTS) { // 如果自定義的concurrencyLevel超過允許最大的并發數 concurrencyLevel = MAX_SEGMENTS; // 設定為允許的最大的并發數}int sshift = 0;int ssize = 1;while (ssize < concurrencyLevel) { ++sshift; // 為了能夠使用按位與的散列算法來定位segments數組的索引, 必須保證segments數組的長度是2的N次方 // 例如concurrencyLevel是14, 15或者16, 那么鎖的個數也總是16 ssize <<= 1;}segmentShift = 32 -sshift; // 用于定位參與散列運算的位數長度segmentMask = ssize - 1; // 散列運算的掩碼, 各個二進制位都是1this.segments = Segment.newArray(ssize); // 創建Segment數組

初始化單個segment

if (initialCapacity > MAXIMUM_CAPACITY) { // 如果自定義的Capacity超過了單個segment允許的最大的Capacity initialCapacity = MAXIMUM_CAPACITY; // 設定為單個segment允許的最大的Capacity}int c = initialCapacity / ssize; // 計算單個segment下的HashEntry數組的長度基值if (c * ssize < initialCapacity) { // 確保數組能夠容納所有鍵值對 ++c;}int cap = 1;while (cap < c) { cap <<= 1; // 將HashEntry的長度向2的N次方對齊}for (int i = 0; i < this.segments.length; ++i) { // 初始化各個segment元素, 實際上是創建cap長度的HashEntry數組, loadFactor指定了HashEntry數組總體上允許的最大負載百分比 this.segments[i] = new Segment<K, V>(cap, loadFactor)}

定位Segment 在插入和獲取元素的時候, 必須先通過散列算法定位到Segment, ConcurrentHashMap首先使用Wang/Jenkins hash的變種算法對元素的hashCode進行一次再散列.

變種算法的代碼如下:

// 本段代碼無需理解, 只需要知道是一個對要插入ConcurrentHashMap元素的原始hash值的再散列(hash)的過程即可PRivate static int hash(int h) { h += (h << 15) ^ 0xffffcd7d; h ^= (h >>> 10); h += (h << 3); h ^= (h >>> 6); h += (h << 2) + (h << 14); return h ^ (h >>> 16);}/* 用再散列后的元素的的hash值來定位segment數組索引 */final Segment<K, V> segmentFor(int hash) { // hash 是再散列后的元素的hash值 // 使用hash值的高四位進行Segment數組索引的計算 // 這里假設segmentMask為1111, segmentShift為28, 也就是Segment數組的長度為16 return segments[(hash >>> segmetnShift) & segmentMask]; }

之所以進行再散列, 目的是減少散列沖突, 使元素能夠均勻分布在不同的Segment上. 如若負載不均, 那么分段鎖就會失去意義.

ConcurrentHashMap的操作

主要介紹三種操作: get, putsize操作

get操作

步驟如下:

對元素的原始hash值先進行再散列;通過這個散列值定位到segment數組索引;通過散列算法定位到具體的HashEntry數組中的元素;public V get(Object key) { int hash = hash(key.hashCode()); // 再散列 return segmentFor(hash).get(key, hash); // 點調用segmentFor返回具體的segment, 然后通過hash值獲取元素}

需要注意的是, 定位Segment參與計算是再散列后的hash值的高位, 而定位HashEntry參與計算的是再散列后的has值的低位, 這是為了避免兩次計算使用的hash值相同, 導致元素在Segment中散開了, 但是沒有在HashEntry中散開.

(hash >>> segmentShift) & segmentMask; // 定位Segment數組索引使用高位hash & (tab.length - 1); 定位HashEntry使用低位

get的高效之處在于整個get過程不需要加鎖, 因為valuecount都是volatile類型的值. 所以可以多線程并發讀, 但是寫入仍然是獨占的(對每個數據段獨占).

put操作

put操作是需要加鎖的. 需要完成以下操作:

通過再散列的hash值定位到需要插入的Segment;判斷是否需要對SegmentHashEntry數組進行擴容(通過判斷是否超過 負載因子*總容量 來判斷);定位添加元素的位置;

在擴容的時候, 首先會在當前需要擴容的Segment中創建一個容量是之前兩倍的數組, 然后將原數組里的元素進行再散列后插入到新的數組里. 為了高效, ConcurrentHashMap不會對整個容器進行擴容, 僅會對某個segment進行擴容.

size操作

size操作獲取count的累加值的具體步驟是:

先通過兩次不鎖住segment數組的來累加count;如果統計的過程中, 容器的count出現了變化, 則再采用加鎖的方式統計Segment數組中所有元素的個數.

上述的判斷容器的count是否發生變化是通過一個modCount變量來統計的, 任何會造成count變化的操作, 比如put, remove, clean方法操作元素都會將modCount加1, 所以在進行size操作前后比較modCount元素是否發生變化, 就可以得知容器的大小是否發生變化.

ConcurrentLinkedQueue

是一個線程安全的基于鏈接節點的非阻塞FIFO無界隊列.

對于阻塞算法, 有兩種實現思路:

使用一個鎖, 也就是入隊出隊用同一個鎖使用兩個鎖, 入隊出隊用兩個鎖;

對于非阻塞算法, 可以借助循環CAS的方式來實現(注: 實際上是通過加輕量級鎖的方式, 循環CAS會消耗較多的時間片, 只有確認同步塊運行速度較快的情況才能使用輕量級鎖).

以下是ConcurrentLinkedQueue的結構

ConcurrentLinkedQueue

阻塞隊列

阻塞隊列是支持阻塞的插入和阻塞的移除的隊列.

阻塞的插入 意思是當隊列滿時, 隊列會阻塞插入元素的線程, 直到隊列不滿; 阻塞的移除 意思是在隊列為空時, 獲取元素的線程會等待隊列變為非空;

常見的應用場景是生產者和消費者的場景, 作為二者獲取元素的容器.

java中的阻塞隊列

ArrayBlockingQueue 一個由數組結構組成的有界阻塞隊列LinkedBlockingQueue 一個由鏈表結構組成的有界(初始化和最大值均為Integer.MAX_VALUE大小, 可以看做無界隊列)阻塞隊列PriorityBlockingQueue 一個支持優先級排序的無界阻塞隊列DelayQueue 一個使用優先級隊列實現的無界阻塞隊列, 在創建元素的時候可以指定多久才能從隊列中獲取當前元素, 只有在延遲期滿才能從隊列中提取元素.SynchronousQueue 一個不存儲元素的阻塞隊列, 也就是容量是0, 直接將生產者線程的數據傳遞給消費者. 每一個put操作必須等待一個take操作, 否則會被阻塞LinkedTransferQueue 一個由鏈表結構組成的無界阻塞隊列, 如果有消費者在等待數據, 就直接將生產者的數據傳遞給消費者, 如果沒有消費者在等待獲取數據, 就將數據放置在隊列尾部.LinkedBlockingDeque 一個由鏈表結構組成的雙向阻塞隊列. 由于兩端都可以入隊和出隊, 比前述隊列減少了一半的數據競爭, 可以用在”工作竊取”模式中

未完待續


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日韩中文在线| 欧美日韩国产精品一区二区不卡中文| 欧美性xxxxx| 国产精品尤物福利片在线观看| 日韩成人在线免费观看| 伊人久久综合97精品| 日本精品视频在线播放| 亚洲国产欧美一区二区丝袜黑人| 国产精品久久久久久久久久新婚| 日韩在线视频网站| 亚洲成avwww人| 国产精品露脸自拍| 久久久久亚洲精品成人网小说| 欧美高清视频免费观看| 欧美有码在线观看视频| 欧美中文在线观看国产| 欧美精品videosex性欧美| 欧美国产一区二区三区| 亚洲精品视频在线播放| 亚洲欧美日韩爽爽影院| 亚洲一区二区福利| 亚洲精品99999| 久久久久久久久久亚洲| 亚洲成人黄色在线观看| 国产日韩在线精品av| 欧美大秀在线观看| 中国日韩欧美久久久久久久久| 91精品久久久久久久久| 亚洲男人天堂2019| 国产欧美日韩中文| 亚洲欧美在线一区二区| 在线观看精品国产视频| 欧美电影免费观看大全| 疯狂做受xxxx欧美肥白少妇| 精品久久香蕉国产线看观看gif| 久久夜色精品亚洲噜噜国产mv| 中文字幕在线视频日韩| 亚洲国产欧美一区二区丝袜黑人| 成人写真视频福利网| 自拍偷拍免费精品| 伊人久久男人天堂| 日韩激情av在线免费观看| 永久免费精品影视网站| 国产精品狠色婷| 亚洲最大的网站| 亚洲欧美日韩天堂一区二区| 国产69精品久久久久9999| 欧美黑人狂野猛交老妇| 在线观看中文字幕亚洲| 国产中文字幕日韩| 91精品在线观| 国产精品久久久久久久久久久久| 久久久久久成人| 中文字幕欧美精品日韩中文字幕| 久久电影一区二区| 波霸ol色综合久久| 欧美日韩在线观看视频| 日韩欧美成人区| 亚洲色图第三页| 久久久免费精品| 日韩在线视频观看正片免费网站| 国产91在线高潮白浆在线观看| 欧美成人午夜视频| 精品国模在线视频| 91精品国产91久久久久福利| 精品精品国产国产自在线| 国产一区二区日韩| 久久久久久尹人网香蕉| 国产在线观看不卡| 亚洲欧洲国产一区| 欧美刺激性大交免费视频| 日韩精品亚洲视频| 韩国欧美亚洲国产| 亲子乱一区二区三区电影| 欧美性猛交丰臀xxxxx网站| 色无极影院亚洲| 日韩精品在线影院| 久久综合免费视频影院| 日本中文字幕成人| 亚洲开心激情网| 国产精品久久网| 亚洲欧美日韩直播| 在线看日韩欧美| 欧美一乱一性一交一视频| 国产小视频91| 久久影视电视剧免费网站清宫辞电视| 国产精品美女www爽爽爽视频| 国模私拍一区二区三区| 久久资源免费视频| 欧美大奶子在线| 欧美性xxxx极品hd欧美风情| 欧美综合国产精品久久丁香| 懂色aⅴ精品一区二区三区蜜月| 欧美日韩国产影院| 国产精品一区二区久久久久| 亚洲男人天堂2019| 精品国产精品自拍| 97精品欧美一区二区三区| 亚洲国产精品va在线看黑人动漫| 欧美极品在线视频| 黑人巨大精品欧美一区免费视频| 亚洲人成在线一二| 免费99精品国产自在在线| 久久精品国产一区二区电影| 国产免费一区视频观看免费| 精品高清一区二区三区| 国产精品尤物福利片在线观看| 孩xxxx性bbbb欧美| 欧美国产精品人人做人人爱| 中文字幕精品影院| 欧美大学生性色视频| 亚洲精品国产精品国自产观看浪潮| 中文字幕欧美精品在线| 国产精品啪视频| 国产欧美久久一区二区| 国产精品日韩在线一区| 亚洲а∨天堂久久精品9966| 久久久黄色av| 中文字幕亚洲综合久久| 日韩精品日韩在线观看| 第一福利永久视频精品| 亚洲激情视频网| 日韩美女视频中文字幕| 91豆花精品一区| 国产在线精品自拍| 午夜剧场成人观在线视频免费观看| 午夜精品久久久久久久99热| 亚洲欧美福利视频| 在线丨暗呦小u女国产精品| 精品国产31久久久久久| 国产欧美中文字幕| 欧美交受高潮1| 久久好看免费视频| 久久男人的天堂| 国产精品午夜国产小视频| 国产亚洲欧美日韩一区二区| 国产精品精品一区二区三区午夜版| 91精品视频免费| 欧美在线观看一区二区三区| 国产精品欧美激情在线播放| 亚洲免费av片| 亚洲国产欧美日韩精品| 亚洲iv一区二区三区| 日韩高清人体午夜| 69**夜色精品国产69乱| 亚洲一区二区久久| 91精品国产综合久久香蕉922| 91精品国产自产在线观看永久| 国产欧美精品xxxx另类| 在线观看国产精品91| 97久久精品国产| 亚洲精品不卡在线| 亚洲乱码一区av黑人高潮| 亚洲精品久久久久中文字幕二区| 这里只有视频精品| 91精品久久久久久久久不口人| 91po在线观看91精品国产性色| 国产91|九色| 亚洲欧美在线一区二区| 久久久亚洲福利精品午夜| 国产成人自拍视频在线观看| 国内精品久久久久伊人av| 亚洲美女免费精品视频在线观看| 亚洲国产成人av在线|