我有一個地圖,該地圖將同時被多個線程修改。 java
Java API中彷佛有三種不一樣的同步Map實現: 安全
Hashtable
Collections.synchronizedMap(Map)
ConcurrentHashMap
據我瞭解, Hashtable
是一箇舊的實現(擴展了過期的Dictionary
類),後來對其進行了調整以適合Map
接口。 雖然它是同步的,但彷佛存在嚴重的可伸縮性問題 ,所以不建議用於新項目。 併發
可是其餘兩個呢? Collections.synchronizedMap(Map)
和ConcurrentHashMap
返回的Collections.synchronizedMap(Map)
之間有什麼區別? 哪種適合哪一種狀況? app
在ConcurrentHashMap
,該鎖將應用於段而不是整個Map。 每一個段都管理本身的內部哈希表。 該鎖僅適用於更新操做。 Collections.synchronizedMap(Map)
同步整個地圖。 ide
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗ ║ Property ║ HashMap ║ Hashtable ║ ConcurrentHashMap ║ ╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣ ║ Null ║ allowed ║ not allowed ║ ║ values/keys ║ ║ ║ ╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣ ║Is thread-safe ║ no ║ yes ║ ╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣ ║ Lock ║ not ║ locks the whole ║ locks the portion ║ ║ mechanism ║ applicable ║ map ║ ║ ╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣ ║ Iterator ║ fail-fast ║ weakly consistent ║ ╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝
關於鎖定機制: Hashtable
鎖定對象 ,而ConcurrentHashMap
僅鎖定bucket 。 性能
二者之間的主要區別在於ConcurrentHashMap
將僅鎖定正在更新的數據部分,而其餘線程能夠訪問其餘部分數據。 可是, Collections.synchronizedMap()
將在更新時鎖定全部數據,其餘線程僅在釋放鎖定後才能訪問數據。 若是更新操做不少而讀取操做相對較少,則應選擇ConcurrentHashMap
。 spa
另一個區別是ConcurrentHashMap
不會保留傳入的Map中元素的順序。它在存儲數據時相似於HashMap
。 不能保證保留元素順序。 雖然Collections.synchronizedMap()
將保留在經過Map的元素順序。例如,若是你傳遞一個TreeMap
來ConcurrentHashMap
,這些元素才能在ConcurrentHashMap
可能不同,在順序TreeMap
,但Collections.synchronizedMap()
將保留順序。 .net
此外, ConcurrentHashMap
能夠保證在一個線程更新映射而另外一個線程遍歷從映射得到的迭代器時,不會引起ConcurrentModificationException
。 可是,對此不保證Collections.synchronizedMap()
。 線程
有一篇文章展現了這二者的區別以及ConcurrentSkipListMap
。 code
併發哈希圖
SynchronizedHashMap