Collections.synchronizedMap() 和 ConcurrentHashMap 区别

原文链接:https://zhuanlan.zhihu.com/p/613889543


Map<String, Object> map1 = new HashMap<String, Object>();
Map<String, Object> map2 = new Hashtable<String, Object>();
Map<String, Object> map3 = new ConcurrentHashMap<String, Object>();
Map<String, Object> map4 = Collections.synchronizedMap(new HashMap<String, Object>());

线程安全方式不同

Collections.synchronizedMap 在每个方法上都使用了 synchronized 关键字进行同步,
ConcurrentHashMap 利用了分段锁(Segment)来实现线程安全,将一个大的 Map 分成了多个小的 Segment,每个 Segment 都有自己的锁,不同的线程可以同时访问不同的 Segment,从而提高了并发性能。

线程安全级别不同

Collections.synchronizedMap 只能保证对 Map 的单个操作是原子性的,而不能保证对多个操作的原子性,因此在多线程环境下需要使用者自己保证操作的原子性。
比如:map在读取与清空之间,线程间是不同步的。正确的方法是,把map的读取和清空看成一个原子操作,给整个代码块加锁。
ConcurrentHashMap 可以保证对多个操作的原子性。

迭代器不同

Collections.synchronizedMap 中的迭代器是同步的,即在迭代期间其他线程不能修改 Map 中的内容,
ConcurrentHashMap 中的迭代器是弱一致性的,即在迭代期间其他线程可以修改 Map 中的内容,但是不保证迭代器能够访问到最新的修改。

空值不同

ConcurrentHashMap 不允许存储null,
Collections.synchronizedMap 可以存储null。

内存占用不同

ConcurrentHashMap 采用了分段锁的方式来实现线程安全,因此在内存占用上比 Collections.synchronizedMap 更高。

扩容方式不同

ConcurrentHashMap 的扩容方式是通过增加 Segment 的数量来实现的,而 Collections.synchronizedMap 的扩容方式是通过创建一个新的 Map,并将旧的 Map 中的内容复制到新的 Map 中来实现的。

底层实现不同

Collections.synchronizedMap 是使用一个包装器类来实现的。
ConcurrentHashMap 是使用数组和链表来实现的


总结
ConcurrentHashMap 在高并发的情况下性能更好
Collections.synchronizedMap 在低并发的情况下更加简单易用。
因此,应该根据实际情况选择适合的线程安全 Map 实现类。


Further Reading

synchronizedMap 和 concurrenthashmap 分别适用于什么场景?
Collections.synchronizedMap()与ConcurrentHashMap的区别

你可能感兴趣的:(集合,算法题,java)