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

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

哈希表 collections . synchronizedmap(地图) ConcurrentHashMap

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

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


当前回答

除了ConcurrentHashMap提供的并发特性之外,还有一个重要的特性需要注意,那就是故障安全迭代器。我见过开发人员使用ConcurrentHashMap只是因为他们想编辑条目集——在迭代时放置/删除它。 synchronizedmap (Map)不提供故障安全迭代器,但它提供了快速故障迭代器。快速失败迭代器使用映射大小的快照,在迭代过程中不能编辑。

其他回答

除了ConcurrentHashMap提供的并发特性之外,还有一个重要的特性需要注意,那就是故障安全迭代器。我见过开发人员使用ConcurrentHashMap只是因为他们想编辑条目集——在迭代时放置/删除它。 synchronizedmap (Map)不提供故障安全迭代器,但它提供了快速故障迭代器。快速失败迭代器使用映射大小的快照,在迭代过程中不能编辑。

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

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

我们可以通过使用ConcurrentHashMap和synchronisedHashmap和Hashtable来实现线程安全。但如果你看看他们的架构,就会发现有很多不同。

synchronisedHashmap和Hashtable

两者都将在对象级别上维护锁。所以如果你想执行任何操作,比如put/get,那么你必须先获得锁。同时,其他线程不允许执行任何操作。所以在同一时间,只有一个线程可以操作这个。所以这里的等待时间会增加。我们可以说,与ConcurrentHashMap相比,性能相对较低。

ConcurrentHashMap

It will maintain the lock at segment level. It has 16 segments and maintains the concurrency level as 16 by default. So at a time, 16 threads can be able to operate on ConcurrentHashMap. Moreover, read operation doesn't require a lock. So any number of threads can perform a get operation on it. If thread1 wants to perform put operation in segment 2 and thread2 wants to perform put operation on segment 4 then it is allowed here. Means, 16 threads can perform update(put/delete) operation on ConcurrentHashMap at a time. So that the waiting time will be less here. Hence the performance is relatively better than synchronisedHashmap and Hashtable.

以下是一些例子:

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

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

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

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

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

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