看初始化**,跟hashmap不一致,concurrenthashmap初始化容量是2的n次冪+2的n-1次冪+1,其中n滿足2的n次冪大於或等於初始容量,2的n-1次冪小於等於初始容量
public concurrenthashmap(intinitialcapacity)
然後檢視變數值可以看到,基本上的變數都採用了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基本一致,唯一不一致。
publicv 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其他快取資料失效,因此讀操作沒有加鎖也是執行緒安全的不會讀取到髒資料
staticclass nodeimplements map.entry
put操作主要是通過cas來保證向沒有key存在的entry裡面新增元素。如果說hash值衝突,就通過sychronized來避免多執行緒同時新增,如果不鎖住會發生乙個節點的next已經新增了乙個值然後另乙個執行緒替代了這個值或者操作不成功。其餘操作和hashmap基本類似
final v putval(k key, v value, booleanonlyifabsent)
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值來保證**的執行緒安全和一致性。
publicv 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是執行緒安全的,由於分...