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

首頁 > 編程 > Java > 正文

java無鎖hashmap原理與實現詳解

2019-11-26 15:48:53
字體:
來源:轉載
供稿:網友

java多線程環境中應用HashMap,主要有以下幾種選擇:使用線程安全的java.util.Hashtable作為替代​使用java.util.Collections.synchronizedMap方法,將已有的HashMap對象包裝為線程安全的。使用java.util.concurrent.ConcurrentHashMap類作為替代,它具有非常好的性能。
而以上幾種方法在實現的具體細節上,都或多或少地用到了互斥鎖?;コ怄i會造成線程阻塞,降低運行效率,并有可能產生死鎖、優先級翻轉等一系列問題。

CAS(Compare And Swap)是一種底層硬件提供的功能,它可以將判斷并更改一個值的操作原子化。

Java中的原子操作

在java.util.concurrent.atomic包中,Java為我們提供了很多方便的原子類型,它們底層完全基于CAS操作。

例如我們希望實現一個全局公用的計數器,那么可以:

復制代碼 代碼如下:

privateAtomicInteger counter =newAtomicInteger(3);

publicvoidaddCounter() {

    for(;;) {

        intoldValue = counter.get();

        intnewValue = oldValue +1;

        if(counter.compareAndSet(oldValue, newValue))

            return;

    }

}

其中,compareAndSet方法會檢查counter現有的值是否為oldValue,如果是,則將其設置為新值newValue,操作成功并返回true;否則操作失敗并返回false。

當計算counter新值時,若其他線程將counter的值改變,compareAndSwap就會失敗。此時我們只需在外面加一層循環,不斷嘗試這個過程,那么最終一定會成功將counter值+1。(其實AtomicInteger已經為常用的+1/-1操作定義了 incrementAndGet與decrementAndGet方法,以后我們只需簡單調用它即可)

除了AtomicInteger外,java.util.concurrent.atomic包還提供了AtomicReference和AtomicReferenceArray類型,它們分別代表原子性的引用和原子性的引用數組(引用的數組)。

無鎖鏈表的實現
在實現無鎖HashMap之前,讓我們先來看一下比較簡單的無鎖鏈表的實現方法。

以插入操作為例:

首先我們需要找到待插入位置前面的節點A和后面的節點B。
然后新建一個節點C,并使其next指針指向節點B。(見圖1)
最后使節點A的next指針指向節點C。(見圖2)

但在操作中途,有可能其他線程在A與B直接也插入了一些節點(假設為D),如果我們不做任何判斷,可能造成其他線程插入節點的丟失。(見圖3)我們可以利用CAS操作,在為節點A的next指針賦值時,判斷其是否仍然指向B,如果節點A的next指針發生了變化則重試整個插入操作。大致代碼如下:

復制代碼 代碼如下:

privatevoidlistInsert(Node head, Node c) {

 
    for(;;) {

 
        Node a = findInsertionPlace(head), b = a.next.get();

 
        c.next.set(b);

        if(a.next.compareAndSwap(b,c))

            return;
    }
}

(Node類的next字段為AtomicReference<Node>類型,即指向Node類型的原子性引用)

無鎖鏈表的查找操作與普通鏈表沒有區別。而其刪除操作,則需要找到待刪除節點前方的節點A和后方的節點B,利用CAS操作驗證并更新節點A的next指針,使其指向節點B。

無鎖HashMap的難點與突破
HashMap主要有插入、刪除、查找以及ReHash四種基本操作。一個典型的HashMap實現,會用到一個數組,數組的每項元素為一個節點的鏈表。對于此鏈表,我們可以利用上文提到的操作方法,執行插入、刪除以及查找操作,但對于ReHash操作則比較困難。

如圖4,在ReHash過程中,一個典型的操作是遍歷舊表中的每個節點,計算其在新表中的位置,然后將其移動至新表中。期間我們需要操縱3次指針:

將A的next指針指向D
將B的next指針指向C​
將C的next指針指向E
而這三次指針操作必須同時完成,才能保證移動操作的原子性。但我們不難看出,CAS操作每次只能保證一個變量的值被原子性地驗證并更新,無法滿足同時驗證并更新三個指針的需求。

于是我們不妨換一個思路,既然移動節點的操作如此困難,我們可以使所有節點始終保持有序狀態,從而避免了移動操作。在典型的HashMap實現中,數組的長度始終保持為2i,而從Hash值映射為數組下標的過程,只是簡單地對數組長度執行取模運算(即僅保留Hash二進制的后i位)。當ReHash時,數組長度加倍變為2i+1,舊數組第j項鏈表中的每個節點,要么移動到新數組中第j項,要么移動到新數組中第j+2i項,而它們的唯一區別在于Hash值第i+1位的不同(第i+1位為0則仍為第j項,否則為第j+2i項)。

如圖5,我們將所有節點按照Hash值的翻轉位序(如1101->1011)由小到大排列。當數組大小為8時,2、18在一個組內;3、 11、27在另一個組內。每組的開始,插入一個哨兵節點,以方便后續操作。為了使哨兵節點正確排在組的最前方,我們將正常節點Hash的最高位(翻轉后變為最低位)置為1,而哨兵節點不設置這一位。

當數組擴容至16時(見圖6),第二組分裂為一個只含3的組和一個含有11、27的組,但節點之間的相對順序并未改變。這樣在ReHash時,我們就不需要移動節點了。

實現細節

由于擴容時數組的復制會占用大量的時間,這里我們采用了將整個數組分塊,懶惰建立的方法。這樣,當訪問到某下標時,僅需判斷此下標所在塊是否已建立完畢(如果沒有則建立)。

另外定義size為當前已使用的下標范圍,其初始值為2,數組擴容時僅需將size加倍即可;定義count代表目前HashMap中包含的總節點個數(不算哨兵節點)。

初始時,數組中除第0項外,所有項都為null。第0項指向一個僅有一個哨兵節點的鏈表,代表整條鏈的起點。初始時全貌見圖7,其中淺綠色代表當前未使用的下標范圍,虛線箭頭代表邏輯上存在,但實際未建立的塊。

初始化下標操作

數組中為null的項都認為處于未初始化狀態,初始化某個下標即代表建立其對應的哨兵節點。初始化是遞歸進行的,即若其父下標未初始化,則先初始化其父下標。(一個下標的父下標是其移除最高二進制位后得到的下標)大致代碼如下:

復制代碼 代碼如下:

privatevoidinitializeBucket(intbucketIdx) {

    intparentIdx = bucketIdx ^ Integer.highestOneBit(bucketIdx);

    if(getBucket(parentIdx) ==null)

        initializeBucket(parentIdx);

    Node dummy =newNode();

    dummy.hash = Integer.reverse(bucketIdx);

    dummy.next =newAtomicReference<>();

    setBucket(bucketIdx, listInsert(getBucket(parentIdx), dummy));

 
}

其中getBucket即封裝過的獲取數組某下標內容的方法,setBucket同理。listInsert將從指定位置開始查找適合插入的位置插入給定的節點,若鏈表中已存在hash相同的節點則返回那個已存在的節點;否則返回新插入的節點。

插入操作

首先用HashMap的size對鍵的hashCode取模,得到應插入的數組下標。
然后判斷該下標處是否為null,如果為null則初始化此下標。
構造一個新的節點,并插入到適當位置,注意節點中的hash值應為原hashCode經過位翻轉并將最低位置1之后的值。
將節點個數計數器加1,若加1后節點過多,則僅需將size改為size*2,代表對數組擴容(ReHash)。

查找操作

找出待查找節點在數組中的下標。
判斷該下標處是否為null,如果為null則返回查找失敗。
從相應位置進入鏈表,順次尋找,直至找出待查找節點或超出本組節點范圍。

刪除操作

找出應刪除節點在數組中的下標。
判斷該下標處是否為null,如果為null則初始化此下標。
找到待刪除節點,并從鏈表中刪除。(注意由于哨兵節點的存在,任何正常元素只被其唯一的前驅節點所引用,不存在被前驅節點與數組中指針同時引用的情況,從而不會出現需要同時修改多個指針的情況)
將節點個數計數器減1。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产日韩在线看| 国产精品扒开腿爽爽爽视频| 亚洲精品视频在线播放| 超碰精品一区二区三区乱码| 欧美一区二区.| 欧美日韩国产色视频| 国产精品午夜一区二区欲梦| 欧美激情精品久久久久| 欧美激情一区二区三区成人| 亚洲加勒比久久88色综合| 久久久999国产| 亚洲成人免费网站| 国产成人精品一区| 国产精品99一区| 欧美日韩免费在线| 黑人极品videos精品欧美裸| 成人有码在线视频| 国产午夜精品全部视频播放| 日韩免费在线播放| 国产中文字幕日韩| 欧美孕妇性xx| 国产精品一区二区三区久久| 欧美放荡办公室videos4k| 国产女人精品视频| 亚洲欧美在线一区二区| 欧美肥老妇视频| 久久人人爽人人爽爽久久| 欧美一区二三区| 亚洲曰本av电影| 在线精品视频视频中文字幕| 欧美性一区二区三区| 久久av红桃一区二区小说| 亚州欧美日韩中文视频| 色悠久久久久综合先锋影音下载| 亚洲石原莉奈一区二区在线观看| 亚洲黄在线观看| 久久69精品久久久久久国产越南| 欧美巨猛xxxx猛交黑人97人| 亚洲图片欧洲图片av| 国产成人一区二区三区小说| 久久av.com| 亚洲大胆美女视频| 亚洲性视频网站| 国产精品视频xxx| 亚洲国产欧美一区二区丝袜黑人| 日韩免费观看网站| 国产精品久久色| 国产精品入口尤物| 日韩美女主播视频| 欧美性猛交xxxx乱大交蜜桃| 欧美国产激情18| 亚洲精品国产电影| 日本国产欧美一区二区三区| 亚洲国产成人精品女人久久久| 国产日韩在线一区| 欧美午夜女人视频在线| 亚洲国产成人在线播放| 欧美成人午夜剧场免费观看| 久久久www成人免费精品张筱雨| 久久精品中文字幕免费mv| 91国偷自产一区二区三区的观看方式| 久久中文字幕视频| 亚洲精品欧美极品| 97人人爽人人喊人人模波多| 粉嫩老牛aⅴ一区二区三区| 国产精品久久久久久久久久久久久久| 国产精品一区二区性色av| 精品国偷自产在线视频| 国产欧美精品一区二区三区-老狼| 日韩女优人人人人射在线视频| 日本在线观看天堂男亚洲| 欧美专区在线播放| 国产亚洲欧洲黄色| 欧美性少妇18aaaa视频| 欧美大片欧美激情性色a∨久久| 欧美精品少妇videofree| 精品无人区乱码1区2区3区在线| 色香阁99久久精品久久久| 欧美电影免费观看高清| 5252色成人免费视频| 亚洲精品日韩久久久| 成人xxxx视频| www.美女亚洲精品| 国产精品视频在线播放| 欧美小视频在线观看| 日韩精品中文字幕久久臀| 欧美在线激情网| 欧美国产视频日韩| 裸体女人亚洲精品一区| 国产精品成久久久久三级| 日韩av片永久免费网站| 亚洲国语精品自产拍在线观看| 日本久久久久久| 国产精品91免费在线| 日本精品在线视频| 精品国偷自产在线视频99| 91精品国产91久久久久久不卡| 国产精品美女午夜av| 性色av香蕉一区二区| 国产精品日韩在线播放| 亚洲网址你懂得| 午夜美女久久久久爽久久| 亚洲女同精品视频| 久久精品成人欧美大片| 欧美性开放视频| 日韩av在线电影网| 欧美日韩一二三四五区| 亚洲精品国产精品自产a区红杏吧| 欧美日韩国产中文精品字幕自在自线| 欧美激情久久久| 国产精品久久久久久久久| 国产视频久久久久久久| 国产日本欧美一区| 一本色道久久综合狠狠躁篇的优点| 国产精品黄视频| 亚洲视频在线观看网站| 欧美精品www| 欧美精品一区三区| 欧美一区二区三区四区在线| 欧美日韩亚洲网| 亚洲国产精品中文| 日韩经典一区二区三区| 国产在线观看精品| 亚洲国产成人久久| 久久久久久久久久av| 欧美韩日一区二区| 亚洲精选一区二区| 69视频在线免费观看| 亚洲精品视频在线观看视频| 高清一区二区三区四区五区| 久久6免费高清热精品| 国产婷婷成人久久av免费高清| 色黄久久久久久| 国产精品亚洲网站| 国产+人+亚洲| 亚洲欧美日韩天堂一区二区| 亚洲a∨日韩av高清在线观看| 精品久久久国产| 欧美日韩日本国产| 欧美亚洲成人xxx| 欧美激情图片区| 国产精品海角社区在线观看| 久久久999国产精品| 少妇激情综合网| 欧美影院成年免费版| 亚洲精品wwwww| www亚洲精品| 高清欧美性猛交xxxx| 欧美大片免费观看| 国产精品成人aaaaa网站| 97精品一区二区视频在线观看| 国产成人精品在线观看| 亚洲福利视频在线| 97人人爽人人喊人人模波多| 亚洲国产高清福利视频| 国产视频精品va久久久久久| 精品久久久香蕉免费精品视频| 国产精品视频白浆免费视频| 欧美国产日韩一区二区在线观看| 日韩免费av片在线观看| 国外成人性视频| 欧美性猛交xxxx乱大交极品| 亚洲欧美三级伦理| 国产丝袜一区二区三区|