ConCurrentHashMap原始碼分析

2022-06-10 20:21:09 字數 3871 閱讀 2796

看初始化**,跟hashmap不一致,concurrenthashmap初始化容量是2的n次冪+2的n-1次冪+1,其中n滿足2的n次冪大於或等於初始容量,2的n-1次冪小於等於初始容量

public concurrenthashmap(int

initialcapacity)

然後檢視變數值可以看到,基本上的變數都採用了voltatile修飾,所有volatile變數使用前必須要重新整理

/*

---------------- fields --------------

*//**

* the array of bins. lazily initialized upon first insertion.

* size is always a power of two. accessed directly by iterators.

*/transient

volatile node table;

/*** the next table to use; non-null only while resizing.

*/private

transient

volatile node nexttable;

/*** base counter value, used mainly when there is no contention,

* but also as a fallback during table initialization

* races. updated via cas.

*/private

transient

volatile

long

basecount;

/*** table initialization and resizing control. when negative, the

* table is being initialized or resized: -1 for initialization,

* else -(1 + the number of active resizing threads). otherwise,

* when table is null, holds the initial table size to use upon

* creation, or 0 for default. after initialization, holds the

* next element count value upon which to resize the table.

*/private

transient

volatile

intsizectl;

/*** the next table index (plus one) to split while resizing.

*/private

transient

volatile

inttransferindex;

/*** spinlock (locked via cas) used when resizing and/or creating countercells.

*/private

transient

volatile

intcellsbusy;

/*** table of counter cells. when non-null, size is a power of 2.

*/private

transient

volatile countercell countercells;

然後檢視獲取元素的方法,其中spread方法是將hash值高位和地位混合到一起,然後高位為零獲取乙個hash值,這樣可以減少hash衝突。因為如果map容量較小,hash值的高位經常變化和地位經常不變就會產生所有的求模預算依賴於低位,而低位經常不變化就會發生嚴重衝突,因此採用將高位和地位進行混合可以有效的降低這種衝突。

讀取邏輯和hashmap基本一致,唯一不一致。

public

v get(object key)

else

if (eh < 0)

return (p = e.find(h, key)) != null ? p.val : null

;

while ((e = e.next) != null

) }

return

null

; }

這個node和hashmap裡面的node不一樣的地方有如下。通過volatile修飾val和 next可以保證寫操作立馬同步回主存並且使得多cpu其他快取資料失效,因此讀操作沒有加鎖也是執行緒安全的不會讀取到髒資料

static

class nodeimplements map.entry

put操作主要是通過cas來保證向沒有key存在的entry裡面新增元素。如果說hash值衝突,就通過sychronized來避免多執行緒同時新增,如果不鎖住會發生乙個節點的next已經新增了乙個值然後另乙個執行緒替代了這個值或者操作不成功。其餘操作和hashmap基本類似

final v putval(k key, v value, boolean

onlyifabsent)

else

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

tab =helptransfer(tab, f);

else

node

pred =e;

if ((e = e.next) == null

) }

}else

if (f instanceof

treebin) }}

}if (bincount != 0) }}

addcount(1l, bincount);

return

null

; }

concurrenthashmap的remove方法是如何保證執行緒安全的。通過加鎖和特殊的設定操作,settabat(tab, i, e.next);巧妙的將put和remove操作的衝突化解了。是將next放入原來位置,如果next有變動可以通過重新讀取主記憶體的next值來保證**的執行緒安全和一致性。

public

v remove(object key)

/*** implementation for the four public remove/replace methods:

* replaces node value with v, conditional upon match of cv if

* non-null. if resulting value is null, delete.

*/final

v replacenode(object key, v value, object cv)

break

; }

pred =e;

if ((e = e.next) == null

)

break

; }

}else

if (f instanceof

treebin) }}

}}

if(validated)

break

; }}}

return

null

; }

ConcurrentHashMap原始碼分析

hashmap 先說hashmap,hashmap是執行緒不安全 的,在併發環境下,可能會形成環狀鍊錶 hashtable hashtable和hashmap的實現原理幾乎一樣,差別無非是1.hashtable不允許key和value為null 2.hashtable是執行緒安全的。但是hashta...

ConcurrentHashMap原始碼詳解

成員變數private static final int maximum capacity 1 30 private static final int default capacity 16 static final int max array size integer.max value 8 pr...

concurrentHashMap原始碼分析

concurrenthashmap是hashmap的執行緒安全版本,內部也是使用 陣列 鍊錶 紅黑樹 的結構來儲存元素。相比於同樣執行緒安全的hashtable來說,效率等各方面都有極大地提高。在這裡可以使用上篇那個 進行測試,根據結果可以知道concurrenthashmap是執行緒安全的,由於分...