Java ConcurrentHashMap 和 SynchronizedMap 的区别

Java ConcurrentHashMap 和 SynchronizedMap 的区别

  • java.util.concurrent.ConcurrentHashMap 和 java.util.Collections$SynchronizedMap 两者都是 Java 中线程安全的 Map 实现

ConcurrentHashMap

  • ConcurrentHashMap 是专门为并发环境设计的,性能优势显著,尤其在读多写少或高并发写场景,适用于绝大多数高并发场景(比如缓存、实时计数器和高频数据统计等)
  • ConcurrentHashMap 的 key 和 value 均不允许为 null
  • 提供 putIfAbsent、computeIfAbsent 和 replace 等原子方法,避免手动同步的复杂性

Collections$SynchronizedMap

  • SynchronizedMap 通过包装一个普通的 Map(比如 HashMap)并对其操作进行同步的方式来实现的,大部分的读写操作都用 synchronized 关键字(对象锁)来保证线程安全,而迭代方法没有加锁,所以在使用迭代方法的时候必须要手动处理线程同步问题(避免抛出异常),由于读写操作都需要竞争同一把锁,所以高并发下性能显著下降
  • 常用方法 Collections.synchronizedMap 返回一个 SynchronizedMap 对象
  • SynchronizedMap 比较适合需要简单地将普通非线程安全的 Map 转换为线程安全的 Map 的情况,适用于旧代码兼容场景,需避免在高并发环境中使用
  • 复合操作需要额外同步逻辑
java 复制代码
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
//需要手动加锁才能保证原子性
synchronized (synchronizedMap) { 
    if (!synchronizedMap.containsKey(key)) {
        synchronizedMap.put(key, value);
    }
}
java 复制代码
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
//迭代时必须处理同步
synchronized (synchronizedMap) { 
    for (Map.Entry<String, Integer> entry : synchronizedMap.entrySet()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
}

总结

  • 迭代器:ConcurrentHashMap 是弱一致性的,迭代过程中允许其他线程修改 Map,不会抛出异常,但迭代器可能不会反映最新的修改(仅保证迭代时的数据是线程安全的),而 SynchronizedMap 在迭代过程中如果被其他线程修改时(比如 put 或 remove),会立即抛出异常
  • 空值处理:ConcurrentHashMap 禁止 null 键或值(避免歧义,为了避免出现 get 方法返回 null 无法区分是 key 不存在还是 value 为 null 的情况),而 SynchronizedMap 允许 null 键和值(沿用底层 Map 特性)
  • 锁机制:ConcurrentHashMap 只对需要修改的部分进行加锁,而不是整个 Map,而 SynchronizedMap 使用 synchronized 关键字对整个 Map 对象加锁,读写操作都需要获取全局锁,性能较低
  • 适用场景:ConcurrentHashMap 适用于高并发、高性能要求场景,特别是读多写少的情况,而 SynchronizedMap 则适用于并发程度较低且对性能要求不高的场景,实现简单,兼容性好,如果需要支持 null 键或值,可以选用 SynchronizedMap,如果需要保证迭代操作的强一致性,可以考虑使用 SynchronizedMap 并手动加锁
相关推荐
Meepo_haha22 分钟前
Spring Boot 条件注解:@ConditionalOnProperty 完全解析
java·spring boot·后端
sheji341633 分钟前
【开题答辩全过程】以 基于springboot的房屋租赁系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
木井巳39 分钟前
【递归算法】子集
java·算法·leetcode·决策树·深度优先
行百里er2 小时前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·代码规范
ms_27_data_develop2 小时前
Java枚举类、异常、常用类
java·开发语言
xiaohe072 小时前
Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
java·数据库·spring boot
代码飞天2 小时前
wireshark的高级使用
android·java·wireshark
gechunlian882 小时前
Spring Boot中的404错误:原因、影响及处理策略
java·spring boot·后端
岁岁种桃花儿3 小时前
AI超级智能开发系列从入门到上天第四篇:AI应用方案设计
java·服务器·开发语言