MST
星途 面试题库

面试题:Java Collections工具类线程安全集合包装方法在高并发场景下的性能问题

在高并发读写场景下,使用Collections工具类的线程安全集合包装方法(如Collections.synchronizedMap())可能会出现哪些性能问题?针对这些问题,有哪些替代方案?请从原理和适用场景等方面进行分析。
35.0万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

性能问题

  1. 锁粒度大:Collections.synchronizedMap() 使用一个全局锁来同步所有的读写操作。在高并发场景下,这意味着同一时间只有一个线程能够进行读或写操作,其他线程都需要等待锁的释放,从而导致线程竞争激烈,大大降低了并发性能。例如,多个线程同时读取数据时,由于全局锁的存在,即使读操作并不存在数据一致性问题,也需要等待锁,造成不必要的性能损耗。
  2. 读操作性能受影响:由于读操作也需要获取锁,而读操作本身并不会改变数据状态,理论上可以并发执行。但在这种全局锁的机制下,读操作也被串行化,影响了整体的读取性能。

替代方案

  1. ConcurrentHashMap
    • 原理:ConcurrentHashMap 在 JDK1.7 中采用分段锁(Segment)机制,将数据分成多个段,每个段有独立的锁。不同段的数据操作可以并发进行,从而提高并发性能。例如,当一个线程对某一段数据进行写操作时,不会影响其他段的读写操作。在 JDK1.8 中,摒弃了分段锁机制,采用 CAS(Compare - And - Swap)和 synchronized 关键字来实现线程安全。对链表和红黑树的头节点使用 synchronized 锁,大大降低了锁的粒度,提高了并发读写性能。
    • 适用场景:适用于高并发读写场景,尤其是读操作远多于写操作的场景。例如,在缓存系统中,大量的线程可能同时读取缓存数据,偶尔有线程进行数据更新操作,ConcurrentHashMap 能够很好地满足这种需求。
  2. CopyOnWriteArrayList/CopyOnWriteArraySet
    • 原理:CopyOnWriteArrayList 用于 List 类型,CopyOnWriteArraySet 用于 Set 类型。它们的原理是写时复制(Copy - On - Write)。当进行写操作(如添加、修改、删除元素)时,会先复制一份原数组,在新数组上进行操作,操作完成后将原数组引用指向新数组。而读操作直接读取原数组,不需要加锁。这就使得读操作完全无锁,并发性能极高。但由于写操作需要复制数组,开销较大。
    • 适用场景:适用于读多写少的场景。例如,在一些配置信息的存储场景中,配置信息很少变动,但可能会被多个线程频繁读取,这种情况下 CopyOnWriteArrayList 或 CopyOnWriteArraySet 是不错的选择。