Java中ConcurrentHashMap學習
ConcurrentHashMap融合了hashtable和hashmap二者的優勢。
hashtable是做了同步的,hashmap未考慮同步。所以hashmap在單執行緒情況下效率較高。hashtable在的多執行緒情況下,同步操作能保證程式執行的正確性。
但是hashtable每次同步執行的時候都要鎖住整個結構。看下圖:
圖左側清晰的標註出來,lock每次都要鎖住整個結構。
ConcurrentHashMap正是為了解決這個問題而誕生的。
ConcurrentHashMap鎖的方式是稍微細粒度的。 ConcurrentHashMap將hash表分為16個桶(預設值),諸如get,put,remove等常用操作只鎖當前需要用到的桶。
試想,原來 只能一個執行緒進入,現在卻能同時16個寫執行緒進入(寫執行緒才需要鎖定,而讀執行緒幾乎不受限制,之後會提到),併發性的提升是顯而易見的。
更令人驚訝的是ConcurrentHashMap的讀取併發,因為在讀取的大多數時候都沒有用到鎖定,所以讀取操作幾乎是完全的併發操作,而寫操作鎖定的粒度又非常細,比起之前又更加快速(這一點在桶更多時表現得更明顯些)。只有在求size等操作時才需要鎖定整個表。
而在迭代時,ConcurrentHashMap使用了不同於傳統集合的快速失敗迭代器的另一種迭代方式,我們稱為弱一致迭代器。在這種迭代方式中,當iterator被建立後集合再發生改變就不再是丟擲 ConcurrentModificationException,取而代之的是在改變時new新的資料從而不影響原有的數 據,iterator完成後再將頭指標替換為新的資料,這樣iterator執行緒可以使用原來老的資料,而寫執行緒也可以併發的完成改變,更重要的,這保證了多個執行緒併發執行的連續性和擴充套件性,是效能提升的關鍵。
下面分析ConcurrentHashMap的原始碼。主要是分析其中的Segment。因為操作基本上都是在Segment上的。先看Segment內部資料的定義。
從上圖可以看出,很重要的一個是table變數。是一個HashEntry的陣列。Segment就是把資料存放在這個陣列中的。除了這個量,還有諸如loadfactor、modcount等變數。
看segment的get 函式的實現:
加上hashentry的程式碼:
可以看出,hashentry是一個連結串列型的資料結構。
在segment的get函式中,通過getFirst函式得到第一個值,然後就是通過這個值的next,一路找到想要的那個物件。如果不空,則返回。如果為空,則可能是其他執行緒正在修改節點。比如上面說的弱一致迭代器在將指標更改為新值的過程。而之前的 get操作都未進行鎖定,根據bernstein條件,讀後寫或寫後讀都會引起資料的不一致,所以這裡要對這個e重新上鎖再讀一遍,以保證得到的是正確值。readValueUnderLock中就是用了lock()進行加鎖。
put操作已開始就鎖住了整個segment。這是因為修改操作時不能併發的。
同樣,remove操作也是如此(類似put,一開始就鎖住真個segment)。
但要注意一點區別,中間那個for迴圈是做什麼用的呢?(截圖未完全,可以自己找找程式碼檢視一下)。從程式碼來看,就是將定位之後的所有entry克隆並拼回前面去,但有必要嗎?每次刪除一個元素就要將那之前的元素克隆一遍?這點其實是由entry的不變性來決定的,仔細觀察entry定義,發現除了value,其他 所有屬性都是用final來修飾的,這意味著在第一次設定了next域之後便不能再改變它,取而代之的是將它之前的節點全都克隆一次。至於entry為什麼要設定為不變性,這跟不變性的訪問不需要同步從而節省時間有關。
相關文章
- Java 中 ConcurrentHashMap 原理分析JavaHashMap
- ConcurrentHashMap (jdk1.7)原始碼學習HashMapJDK原始碼
- 學習Java: Java中的字串Java字串
- Java ConcurrentHashmap 解析JavaHashMap
- java學習:Java中的其它類Java
- Java集合--ConcurrentHashMap原理JavaHashMap
- Java併發包原始碼學習系列:JDK1.8的ConcurrentHashMap原始碼解析Java原始碼JDKHashMap
- Java學習中迴圈語句的學習Java
- Java併發指南13:Java 中的 HashMap 和 ConcurrentHashMap 全解析JavaHashMap
- Java學習--Java 中的包裝類Java
- JAVA中“多型”案例學習Java多型
- Java7/8中的HashMap和ConcurrentHashMap全解析JavaHashMap
- Java併發5:ConcurrentHashMapJavaHashMap
- Java併發之ConcurrentHashMapJavaHashMap
- 如何學習Java? 在學習Java的過程中需要掌握哪些技能?Java
- Java中IO流學習總結Java
- java學習中不懂的問題Java
- java學習之道 --- 如何學習java?Java
- Java ConcurrentHashMap (Java程式碼實戰-005)JavaHashMap
- Java併發——ConcurrentHashMap(JDK 1.8)JavaHashMapJDK
- [Java併發]Concurrenthashmap的size()JavaHashMap
- Java併發指南13:Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析JavaHashMap
- java中的列舉型別學習Java型別
- Java中的Map集合學習筆記Java筆記
- Java學習--java中的集合框架、Collection介面、list介面Java框架
- ConcurrentHashMap原始碼解析-Java7HashMap原始碼Java
- 【Java】ConcurrentHashMap執行緒安全技巧JavaHashMap執行緒
- Java 學習Java
- Java學習Java
- Java中的集合框架深度解析:從ArrayList到ConcurrentHashMap的效能考量Java框架HashMap
- Java工程師學習指南(中級篇)Java工程師
- Java工程師學習指南 中級篇Java工程師
- 學習Java中遇到的繼承問題Java繼承
- java學習中問題與解決方式Java
- java學習中對類和物件的理解Java物件
- 新手如何學習Java——Java學習路線圖Java
- Java學習之路 -- Java怎麼學?Java
- 《JAVA學習指南》學習筆記Java筆記