concurrentHashmap是java5支持 高併發、高吞吐量的線程安全HashMap實現.java
實現原理:數組
容許多個修改併發進行,關鍵技術是鎖分離。分爲多個段(segment)來表示不一樣的部分,每一個段就是一個小的hashtable,他們有本身的鎖。安全
有些方法須要跨段,好比size()和containsValue(),它們可能須要鎖定整個表而而不單單是某個段,這須要按順序鎖定全部段,操做完畢後,又按順序釋放全部段的鎖。併發
1:首先看下get操做,一樣ConcurrentHashMap的get操做是直接委託給Segment的get方法,直接看Segment的get方法.高併發
讀操做並不須要加鎖。爲了確保讀操做可以看到最新的值,將value設置成volatile,這避免了加鎖。spa
static final class HashEntry<K,V> { 線程
final K key; 指針
final int hash; rem
volatile V value; get
final HashEntry<K,V> next;
}
第一步是訪問count變量,這是一個volatile變量,因爲全部的修改操做在進行結構修改時都會在最後一步寫count變量,經過這種機制保證get操做可以獲得幾乎最新的結構更新。對於非結構更新,也就是結點值的改變,因爲HashEntry的value變量是volatile的,也能保證讀取到最新的值。接下來就是對hash鏈進行遍歷找到要獲取的結點,若是沒有找到,直接訪回null。對hash鏈進行遍歷不須要加鎖的緣由在於鏈指針next是final的。可是頭指針卻不是final的,這是經過getFirst(hash)方法返回,也就是存在table數組中的值。這使得getFirst(hash)可能返回過期的頭結點,例如,當執行get方法時,剛執行完getFirst(hash)以後,另外一個線程執行了刪除操做並更新頭結點,這就致使get方法中返回的頭結點不是最新的。這是能夠容許,經過對count變量的協調機制,get能讀取到幾乎最新的數據,雖然可能不是最新的。要獲得最新的數據,只有採用徹底的同步。
2:刪除操做remove
獲取段鎖,先定位到段,而後委託段去執行刪除操做。當多個刪除操做並行時,只要不是在同一個段,就能夠同時進行。
3:put
該方法也是在持有段鎖的狀況下執行的,首先判斷是否須要rehash,須要就先rehash。接着是找是否存在一樣一個key的結點,若是存在就直接替換這個結點的值。不然建立一個新的結點並添加到hash鏈的頭部,這時必定要修改modCount和count的值,一樣修改count的值必定要放在最後一步。put方法調用了rehash方法,reash方法實現得也很精巧,主要利用了table的大小爲2^n,這裏就不介紹了