DengQN·一个普通程序员;
【翻译】Difference between ConcurrentHashMap, Hashtable and Synchronized Map in Java
2019-02-18 17:17 65
#使用#不同#安全#线程#并发#容器#中#同步#实现

翻译自:Javarevisited's Blog

ConcurrentHashMap vs Hashtable vs Synchronized Map

虽然这三个类都能多线程安全地在Java并发程序中使用,但是他们之间有者标志性的不同,主要体现在他们是怎么实现他们的线程安全的。

HashTable在Java1.1就已经出现了,使用同步的方法来实现线程安全,Hashtable里的方法都是Synchronized的,这使得它在线程增多的时候会变得很慢。 Synchronized Map和 Hashtable并没有太大的不同,以及它在并发编程的时候提供了相似的性能。hashtable 和 Synchronized Map之间的唯一不同在于后者可以使用Collections.synchronizedMap()方法把任何的Map变成同步版本。

在另一方面,ConcurrentHashMap 是特别设计出来给并发编程使用的。默认地,它同时允许16个线程在没有任何外部的同步措施下读写Map。 由于内部实现了分段锁,所以有相当的拓展性。和SynchronizedMap和Hashtable不一样,它不会把整个Map锁住,而是,把map分段(Segment),然后再给他们都加上锁。 所以在读(get不加锁)比写的性能要高

老实说,Collections 类作为JavaAPI的核心类,我认为,审慎地使用它们是一种艺术。我的个人经验是,使用Array List代替不必要地Vector之类的可以提高Java应用的性能之类的。 在Java5之前,Java Collection框架的一个问题在于缺少可拓展性。

在多线程Java应用中像Hash table和Vector很快会成瓶颈;在Java1.5后提出了拓展性,并推荐了一线不错的并发容器,在数据量大的时候能保持高效。 遗留的的系统,像电子贸易系统以有能快速访问储存的数据的能力作为支持(注:指使用能支持快速高并发的容器)。

在这篇说明中,我们讨论了 ConcurrentHashMap, Hashtable, HashMap 和synchronized Map ,还探讨了在Java中ConcurrentHashMap 、 Hashtable 和 synchronized Map 的不同。在这篇博客中也讨论了Hashtable, HashMap的不同,这些能在面试的时候帮你回答一些问题。

为什么需要ConcurrentHashMap和CopyOnWriteArrayList

同步的容器, 如Hashtable, Vector, Collections.synchronizedMap() 和 Collections.synchronizedList(),提供了可选的线程安全的Map或List实现。 但是, 一些因子让他们不是很适合用在高并发程序中, 比如, 它们范围很大的锁会妨碍他们的拓展性,以及通常在迭代访问的时候需要锁住整个容器来防止ConcurrentModificationException。

ConcurrentHashMap 和 CopyOnWriteArrayList 的实现提供了更高的并发的同时保证了线程安全, 以最小的代价妥协调用者。 ConcurrentHashMap 和 CopyOnWriteArrayList 并不是必要在哪都要用,你也可以使用 HashMap 或 ArrayList, 但是要在特定的情况下(注:并发安全)。在很多并发程序中使用它们可以得到好处。

ConcurrentHashMap 和 Hashtable的不同

所以ConcurrentHashMap 和 Hashtable的不同在哪呢, 都能用在多线程环境,但是 当Hashtable的大小变大的时候性能会有可观的消耗,因为在访问的时候会给整个容器加锁。

ConcurrentHashMap会给数据分段,不管数据量多大,只用关心被加锁的范围。在保证线程安全的前提下,很多其他的读线程在迭代完成之前能够访问容器。

总结一下, 在迭代的时候ConcurrentHashMap只会锁住map的一部分, 但是HashMap会锁住整个map. 这幅图清晰的表达了Java ConcurrentHashMap的内部工作原理。

ConcurrentHashMap

ConcurrentHashMap 和 Collections.synchronizedMap的不同

ConcurrentHashMap 为了并发设计的 并提升了性能 ,HashMap 原生状态下是非同步的 ,使用synchronized Map可以包裹它让它变成同步容器。 有一些ConcurrentHashMap 和 Collections.synchronizedMap的不同:

ConcurrentHashMap不允许 null 键 或 null 值 , synchronized HashMap允许一个 null 键.