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

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

哈希表 collections . synchronizedmap(地图) ConcurrentHashMap

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

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


当前回答

Hashtable的“可伸缩性问题”在Collections.synchronizedMap(Map)中以完全相同的方式呈现——它们使用非常简单的同步,这意味着同一时间只有一个线程可以访问映射。

当您有简单的插入和查找时,这不是什么大问题(除非您做得非常密集),但是当您需要遍历整个Map时,这就变成了一个大问题,对于一个大型Map来说,这可能会花费很长时间——当一个线程这样做时,所有其他线程都必须等待,如果它们想要插入或查找任何东西。

ConcurrentHashMap使用非常复杂的技术来减少对同步的需求,并允许多线程在不同步的情况下进行并行读访问,更重要的是,它提供了一个不需要同步的迭代器,甚至允许在交互期间修改Map(尽管它不保证在迭代期间插入的元素是否会返回)。

其他回答

以下是一些例子:

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

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

ConcurrentHashMap针对并发访问进行了优化。

访问不锁定整个映射,而是使用更细粒度的策略,这提高了可伸缩性。还有专门针对并发访问的功能增强,例如并发迭代器。

ConcurrentHashMap在Java 1.5中作为哈希表的替代品,作为并发包的一部分。使用ConcurrentHashMap,不仅可以安全地在并发多线程环境中使用,而且提供了比Hashtable和synchronizedMap更好的性能,那么您就有了更好的选择。ConcurrentHashMap性能更好,因为它锁定了Map的一部分。它允许并发读操作,同时通过同步写操作来保持完整性。

ConcurrentHashMap是如何实现的

ConcurrentHashMap was developed as alternative of Hashtable and support all functionality of Hashtable with additional ability, so called concurrency level. ConcurrentHashMap allows multiple readers to read simultaneously without using blocks. It becomes possible by separating Map to different parts and blocking only part of Map in updates. By default, concurrency level is 16, so Map is spitted to 16 parts and each part is managed by separated block. It means, that 16 threads can work with Map simultaneously, if they work with different parts of Map. It makes ConcurrentHashMap hight productive, and not to down thread-safety.

如果你对ConcurrentHashMap的一些重要特性感兴趣,以及什么时候应该使用这种Map的实现——我只是放了一个链接到一篇好文章——如何在Java中使用ConcurrentHashMap

哈希表和ConcurrentHashMap不允许空键或空值。 synchronizedmap (Map)同步所有操作(get、put、size等)。 ConcurrentHashMap支持检索的完全并发性,以及可调的更新预期并发性。

像往常一样,这涉及到并发性、开销和速度的权衡。您确实需要考虑应用程序的详细并发需求来做出决定,然后测试您的代码,看看它是否足够好。

我们可以通过使用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.