collections.synchronizedmap通过包装器模式为每个方法加synchronized(mutex)实现线程安全,但复合操作和迭代需手动加锁;适合低并发、读多写少场景。

Java 中的 Collections.synchronizedMap 是一种快速获得线程安全 Map 的方式,但它不是“开箱即用”的完全安全方案——单个操作(如 put、get)是线程安全的,但组合逻辑和迭代仍需手动加锁。
它怎么保证线程安全
内部采用包装器模式,返回一个 SynchronizedMap 实例,该实例持有原始 Map(如 HashMap)引用,并为每个 public 方法加上 synchronized(mutex)。锁对象默认是包装器自身,意味着整个 Map 共享同一把锁。
- 所有基础方法(size、get、put、remove 等)都同步执行
- 锁粒度粗:任意线程调用任一方法,都会阻塞其他线程访问整个 Map
- 不依赖底层 Map 是否线程安全,只靠外层同步控制
哪些操作仍需额外同步
复合操作和遍历行为不在自动同步范围内,否则可能引发竞态或 ConcurrentModificationException。
- 检查再插入(如 if (!map.containsKey(k)) map.put(k, v)):两个操作之间存在窗口期,必须用 synchronized 块包裹
- 迭代遍历(keySet()、entrySet()、values()):返回的 Iterator 本身未同步,须对 syncMap 显式加锁
- 批量操作(如 putAll)虽已同步,但若涉及外部数据一致性校验,仍需统一锁范围
和 ConcurrentHashMap 的关键区别
两者目标一致,但设计哲学和适用场景不同。
- 锁机制:synchronizedMap 是全表独占锁;ConcurrentHashMap 使用分段锁(JDK7)或 CAS + synchronized 细粒度锁(JDK8+)
- 并发性能:读多写少且并发不高时二者差异不大;高并发下 ConcurrentHashMap 吞吐量显著更高
- 语义保障:ConcurrentHashMap 的迭代器弱一致性,不抛异常;synchronizedMap 迭代必须加锁,否则运行时失败
- null 支持:synchronizedMap 包装的 HashMap 可存 null 键/值;ConcurrentHashMap 不允许 null 键或值
适合什么场景使用
它不是过时技术,而是定位清晰的轻量级工具。
- 低并发环境(如配置缓存、单机服务内部状态映射)
- 已有 HashMap 代码需最小改动接入线程安全
- 读操作远多于写操作,且写操作频率很低
- 不需要强一致性迭代,或能接受显式同步成本
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











