ConcurrentHashMap原理解析

2021-10-01 19:17:26 字數 1926 閱讀 1640

concurrenthashmap是jdk提供的乙個執行緒安全的集合類,它內部的結構原理和我們常用的hashmap基本是一致,那我們可以先來認識一下hashmap,這樣基本上也能大致明白concurrenthashmap了。

hashmap與concurrenthashmap都是用來存放一種鍵值對形式的資料,那它們內部的資料結構是怎麼樣的呢?

首先來看看hashmap的put方法

public v put(k key, v value) 

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

put方法中呼叫了putval(),putval方法中主要就是往tab中新增元素,而tab是乙個陣列,即hashmap是通過陣列

來存放資料的。陣列下標是由(n - 1) & hash計算得出的,這是對陣列長度求餘的位運算方法,當n為2的倍數時,

hash%n和(n - 1) & hash兩者結果相同,但(n - 1) & hash更高效,所以hashmap的容量都是2的倍數。

陣列的型別是node的,所以hashmap實際儲存的也是一組key,value的node物件,而不單單是value。

node類是實現entry介面,所以我們可以通過map.entryset()方法去遍歷hashmap。

static class nodeimplements map.entry
hashmap是通過陣列存放資料的,資料對應陣列下標的位置由key的hash值決定,但不同key值的hash值是會重複的,

當hash值重複了,資料會怎樣的儲存?

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newnode(hash, key, value, null);

else

}

}...

}

當陣列下標元素不為空時,陣列元素存放的是乙個鍊錶,bincount >= treeify_threshold - 1(即鍊錶長度為8)時

則會轉化為紅黑樹。

結論

hashmap內部的資料結構是由陣列,鍊錶和紅黑樹組成的,當鍊表長度為8時會轉化為紅黑樹。

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newnode(hash, key, value, null);

put方法中這個部分**表明,當兩個執行緒同時判斷該陣列下標元素為空時,就會導致資料被覆蓋掉的情況。

//省略部分**

...else if ((f = tabat(tab, i = (n - 1) & hash)) == null)

else if ((fh = f.hash) == moved)

tab = helptransfer(tab, f);

else

static final boolean castabat(node tab, int i,

nodec, nodev)

我們可以看到concurrenthashmap中判斷陣列下標元素為空時,呼叫的是castabat,而castabat中引用了unsafe

的compareandswapobject方法,unsafe直接對記憶體進行操作,判斷記憶體的資料中是否為空,再進行賦值。

當陣列下標元素不為空則通過關鍵字synchronized來保證並非安全。

結論

concurrenthashmap執行緒安全的原理是通過cas機制和synchronized加鎖。

ConcurrentHashMap原理解析

什麼是concurrenthashmap?眾所周知,hashmap是一種非常高效的資料結構,但是依舊有它的缺陷。那就是在併發插入資料時,有可能會出現帶環鍊錶,讓下一次的讀操作出現死迴圈。於是為了避免hashmap的執行緒安全問題,concurrenthashmap應運而生。concurrenthas...

ConcurrentHashMap 原理簡要分析

在之前寫過hashtable 與hashmap 兩者之間的異同 通過前面文章,可以知道hashmap 中未進行同步考慮,而 hashtable 則使用了 synchronized 帶來的直接影響就是可選擇,我們可以在單執行緒時使用 hashmap 提高效率,而多執行緒時用 hashtable 來保證...

ConcurrentHashMap 的原理和結構

concurrenthashmap 是乙個高效的執行緒安全的hashmap,它的加鎖機制和hashtable不同,後者用的是低效的synchronized,前者用的是lock。接著前一期的hashmap,先簡單介紹下concurrenthashmap結構,再以它們的主要函式 put 和 get為切入...