1. HashTable
不推薦使用,無腦給各種方法加鎖
2.ConcurrentHashMap
多線程下推薦使用
- 鎖粒度控制
HashTable直接在方法上加synchronized,相當于對哈希表對象加鎖,一個哈希表只有一把鎖。多線程環境下,無論線程如何操作哈希表,都會產生鎖沖突。
而ConcurrentHashMap每個哈希桶都有自己的鎖,哈希表中哈希桶數量很多,大大降低了鎖沖突的概率,性能也大大提升。
- ConcurrentHashMap只對寫加鎖,讀操作不加鎖
也就是說兩個線程同時修改,才會有鎖沖突;兩個線程都讀,沒有鎖沖突;一個線程寫,一個線程讀,也沒有鎖沖突。
為什么一個線程讀一個線程寫沒有鎖沖突?
難道不會讀到修改一半的數據嗎?ConcurrentHashMap在設計的時候,考慮到這個問題,所以保證在讀的時候一定是讀到一整數據(要么是舊版本,要么是新版本,不會是讀到一半的數據)。
并且讀操作也廣泛使用volatile保證讀到的數據是及時的。
- 充分利用CAS特性
像維護元素個數就是通過CAS實現,而不是加鎖;以及使用CAS實現輕量級鎖/自旋鎖等等。
- 對擴容進行特殊處理
HashTable的擴容:當put元素時,發現負載因子超過閾值就觸發擴容,申請一個更大的數組,把原來舊的數據搬運到新的數組上。
上述擴容方式存在很大問題,當元素個數特別多的時候,搬運操作就會開銷非常大。put操作不需要擴容時瞬間完成O(1),但是觸發擴容時就可能卡很久。
ConcurrentHashMap的擴容的時候,舊的數組和新的數組是同時存在的,每次進行哈希表操作都會把舊數組上的元素搬運一部分到新數組上,直到全部搬運完,再釋放舊的空間。在這個過程中如果要查詢元素,舊的數組和新的數組一起查;如果要插入元素,直接往新數組上插入;如果是刪除元素,直接刪除不用搬運。
- 面試題:HashMap,HashTable,ConcurrentHahMap的區別?
先說HashMap是線程不安全的,HashTable,ConcurrentHashMap是線程安全的。
再談ConcurrentHashMap的優化