线程安全Collections.synchronizedMap与并发ConcurrentHashMap之间区别
Collections.synchronizedMap()和ConcurrentHashMap都提供对数据集合的线程安全操作。
SynchronizedMap:
- 每个方法都使用对象级锁进行同步。因此,synchMap 上的 get 和 put 方法都会获取一个锁。
- 锁定整个集合会造成性能开销。当一个线程锁定时,其他线程无法使用该集合。
ConcurrentHashMap:
- 在对象级别没有锁定,锁定的粒度要细得多。对于并发哈希表(ConcurrentHashMap),锁定可能是在哈希表桶级别。
- 低级锁定的效果是,你可以拥有同步集合无法实现的并发读写器。这将大大提高可扩展性。
- HashMap不是线程安全的,因此在线程争用期间可能会导致错误的结果ConcurrentHashMap 。
- 如果一个线程试图修改 ConcurrentHashMap,而另一个线程正在对其进行迭代,ConcurrentHashMap 不会抛出 ConcurrentModificationException 异常。
- 在ConcurrentHashMap 中,读取操作是非阻塞的,而写入操作则需要锁定特定段或存储桶。默认存储桶或并发级别为 16,这意味着 16 个线程在锁定段或存储桶后可以随时写入。
使用决策:
- ConcurrentHashMap 的 性能优于Collections.synchronizedMap()。
- 当数据一致性至关重要时,我们应该选择Collections.synchronizedMap() ;
- 对于写操作远多于读操作的性能关键型应用程序,我们应该选择ConcurrentHashMap 。
这是因为:
- Collections.synchronizedMap()要求每个线程为读/写操作获取整个对象的锁。
- 相比之下,ConcurrentHashMap允许线程获取集合的不同段上的锁,并同时进行修改。