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

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

哈希表 collections . synchronizedmap(地图) ConcurrentHashMap

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

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


当前回答

如果数据一致性非常重要-使用Hashtable或Collections.synchronizedMap(Map)。 如果速度/性能非常重要,数据更新可能会受到影响-使用ConcurrentHashMap。

其他回答

如果数据一致性非常重要-使用Hashtable或Collections.synchronizedMap(Map)。 如果速度/性能非常重要,数据更新可能会受到影响-使用ConcurrentHashMap。

ConcurrentHashMap

ConcurrentHashMap for performance-critical applications where there are far more write operations than there are read operations. It is thread safe without synchronizing the whole map. Reads can happen very fast while write is done with a lock. There is no locking at the object level. The locking is at a much finer granularity at a hashmap bucket level. ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it. ConcurrentHashMap uses multitude of locks. read operations are non-blocking, whereas write operations take a lock on a particular segment or bucket.

SynchronizedHashMap

对象级同步。 每个读/写操作都需要获得锁。 锁定整个集合是一种性能开销。 这实际上只允许一个线程访问整个映射,并阻塞了所有其他线程。 这可能会引起争论。 SynchronizedHashMap返回迭代器,它在并发修改时快速失败。

Collection.synchronizedMap ()

Collections实用程序类提供了操作集合并返回包装集合的多态算法。它的synchronizedMap()方法提供了线程安全的功能。 当数据一致性至关重要时,我们需要使用Collections.synchronizedMap()。

╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   Property    ║     HashMap       ║    Hashtable      ║  ConcurrentHashMap  ║
╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣ 
║      Null     ║     allowed       ║              not allowed                ║
║  values/keys  ║                   ║                                         ║
╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣
║ Thread-safety ║                   ║                                         ║
║   features    ║       no          ║                  yes                    ║
╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣
║     Lock      ║       not         ║ locks the whole   ║ locks the portion   ║        
║  mechanism    ║    applicable     ║       map         ║                     ║ 
╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣
║   Iterator    ║               fail-fast               ║ weakly consistent   ║ 
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝

关于锁定机构: Hashtable锁定对象,而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

同步地图:

Synchronized Map与Hashtable也没有太大区别,在并发Java程序中提供了类似的性能。哈希表和SynchronizedMap之间的唯一区别是SynchronizedMap不是遗留的,您可以使用Collections.synchronizedMap()方法包装任何Map来创建它的同步版本。

ConcurrentHashMap:

ConcurrentHashMap类提供了标准HashMap的并发版本。这是对Collections类中提供的synchronizedMap功能的改进。

与哈希表和同步映射不同,它从不锁定整个映射,而是将映射划分为段,并在这些段上锁定。如果读取线程的数量大于写入线程的数量,它的性能会更好。

默认情况下,ConcurrentHashMap被划分为16个区域,并应用了锁。这个默认值可以在初始化ConcurrentHashMap实例时设置。当在特定的段中设置数据时,将获得该段的锁。这意味着如果两个更新分别影响不同的存储桶,那么它们仍然可以同时安全执行,从而最大限度地减少锁争用,从而最大化性能。

ConcurrentHashMap不会抛出ConcurrentModificationException异常

如果一个线程试图修改它,而另一个线程正在遍历它,ConcurrentHashMap不会抛出ConcurrentModificationException

synchronizedmap和ConcurrentHashMap的区别

collections . synchronnizedmap (HashMap)将返回一个几乎相当于Hashtable的集合,其中Map上的每个修改操作都锁定在Map对象上,而对于ConcurrentHashMap,线程安全是通过根据并发级别将整个Map划分为不同的分区,只锁定特定的部分而不是锁定整个Map来实现的。

ConcurrentHashMap不允许空键或空值,而synchronized HashMap允许一个空键。

类似的链接

Link1

Link2

性能比较