我有一个映射,这是由几个线程并发修改。

在Java API中似乎有三种不同的同步Map实现:

哈希表 collections . synchronizedmap(地图) ConcurrentHashMap

根据我的理解,Hashtable是一个旧的实现(扩展了过时的Dictionary类),后来为了适应Map接口而进行了调整。虽然它是同步的,但它似乎有严重的可伸缩性问题,不推荐用于新项目。

那另外两个呢?Collections.synchronizedMap(Map)和ConcurrentHashMaps返回的Map之间有什么区别?哪一种适合哪种情况?


当前回答

在ConcurrentHashMap中,锁应用于一个段而不是整个Map。 每个段管理自己的内部哈希表。该锁仅应用于更新操作。synchronizedmap (Map)同步整个映射。

其他回答

一般来说,如果你想使用ConcurrentHashMap,确保你已经准备好错过“更新”(即打印HashMap的内容并不能确保它会打印最新的Map),并使用CyclicBarrier等api来确保程序生命周期的一致性。

如果可以使用ConcurrentHashMap,则首选它——尽管它至少需要Java 5。

它被设计成在多线程使用时可以很好地扩展。当一次只有一个线程访问Map时,性能可能会稍微差一些,但当多个线程并发访问映射时,性能会显著提高。

我找到了一篇博客文章,它复制了优秀的《Java并发实践》一书中的一个表格,我强烈推荐这本书。

集合。synchronizedMap只有在需要用其他特征(可能是某种有序映射,如TreeMap)来包装映射时才有意义。

两者之间的主要区别是ConcurrentHashMap将只锁定正在更新的部分数据,而其他部分数据可以由其他线程访问。但是,Collections.synchronizedMap()将在更新时锁定所有数据,其他线程只能在释放锁时访问数据。如果更新操作较多,读操作相对较少,则选择ConcurrentHashMap。

Also one other difference is that ConcurrentHashMap will not preserve the order of elements in the Map passed in. It is similar to HashMap when storing data. There is no guarantee that the element order is preserved. While Collections.synchronizedMap() will preserve the elements order of the Map passed in. For example, if you pass a TreeMap to ConcurrentHashMap, the elements order in the ConcurrentHashMap may not be the same as the order in the TreeMap, but Collections.synchronizedMap() will preserve the order.

此外,ConcurrentHashMap可以保证当一个线程更新映射而另一个线程遍历从映射中获得的迭代器时,不会抛出ConcurrentModificationException。但是,Collections.synchronizedMap()在此上不被保证。

有一篇文章展示了这两者的区别,还有ConcurrentSkipListMap。

根据您的需要,使用ConcurrentHashMap。它允许从多个线程并发修改Map,而不需要阻塞它们。synchronizedmap (map)创建了一个阻塞map,这会降低性能,但确保了一致性(如果使用得当)。

如果您需要确保数据的一致性,并且每个线程需要有一个最新的映射视图,则使用第二个选项。如果性能非常关键,并且每个线程只向映射中插入数据,读取频率较低,则使用第一种方法。

以下是一些例子:

1) ConcurrentHashMap只锁定Map的一部分,而SynchronizedMap锁定整个Map。 2) ConcurrentHashMap比SynchronizedMap性能更好,扩展性更强。 3)在多读取器和单写入器的情况下,ConcurrentHashMap是最好的选择。

此文本来自Java中的ConcurrentHashMap和哈希表之间的差异