1. 程式人生 > >2w+長文帶你剖析ConcurrentHashMap~!

2w+長文帶你剖析ConcurrentHashMap~!

併發程式設計實踐中,ConcurrentHashMap是一個經常被使用的資料結構,相比於Hashtable以及Collections.synchronizedMap(),ConcurrentHashMap線上程安全的基礎上提供了更好的寫併發能力,但同時降低了對讀一致性的要求(這點好像CAP理論啊 O(∩_∩)O)。ConcurrentHashMap的設計與實現非常精巧,大量的利用了volatile,final,CAS等lock-free技術來減少鎖競爭對於效能的影響,無論對於Java併發程式設計的學習還是Java記憶體模型的理解,ConcurrentHashMap的設計以及原始碼都值得非常仔細的閱讀與揣摩。 這篇日誌記錄了自己對ConcurrentHashMap的一些總結,由於JDK6,7,8中實現都不同,需要分開闡述在不同版本中的ConcurrentHashMap。 本文從原始碼出發,挑選個人覺得重要的點(會用紅色標註)再次進行回顧,以及闡述ConcurrentHashMap的一些注意點。 ## 1. JDK6與JDK7中的實現 #### 1.1 設計思路 ConcurrentHashMap採用了分段鎖的設計,只有在同一個分段內才存在競態關係,不同的分段鎖之間沒有鎖競爭。相比於對整個Map加鎖的設計,分段鎖大大的提高了高併發環境下的處理能力。但同時,由於不是對整個Map加鎖,導致一些需要掃描整個Map的方法(如size(), containsValue())需要使用特殊的實現,另外一些方法(如clear())甚至放棄了對一致性的要求(ConcurrentHashMap是弱一致性的,具體請檢視ConcurrentHashMap能完全替代HashTable嗎?)。 ConcurrentHashMap中的分段鎖稱為Segment,它即類似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry陣列,陣列中的每個元素又是一個連結串列;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。ConcurrentHashMap中的HashEntry相對於HashMap中的Entry有一定的差異性:HashEntry中的value以及next都被volatile修飾,這樣在多執行緒讀寫過程中能夠保持它們的可見性,程式碼如下: ``` static final class H