Collections.synchronizedMap通过方法级synchronized锁实现线程安全,适用于读多写少、低并发场景;但迭代和复合操作需手动同步,性能不如ConcurrentHashMap。

Collections.synchronizedMap 是 Java 提供的一种将普通 Map 包装为线程安全版本的工具方法,它通过在所有 public 方法上加 synchronized 锁来保证并发访问的安全性。但它不是万能方案,用法和限制都需要清楚。
同步包装的本质:方法级锁
它返回的是一个“装饰器”对象(如 SynchronizedMap),内部持有一个原始 map,并对每个公开方法(get、put、remove、size 等)加上同一把锁(通常是 map 自身或指定的 mutex 对象)。
- 每次调用都独占锁,适合读多写少、操作粒度小的场景
- 迭代操作(如
keySet().iterator())不自动同步,需手动加锁保护 - 复合操作(如“检查是否存在再插入”)仍需外部同步,否则存在竞态
常见误用:迭代时未同步
下面这段代码是线程不安全的:
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
for (String key : syncMap.keySet()) { // ❌ 迭代过程未加锁
System.out.println(key + " = " + syncMap.get(key));
}
正确写法是显式同步:
synchronized (syncMap) {
for (String key : syncMap.keySet()) {
System.out.println(key + " = " + syncMap.get(key));
}
}
与 ConcurrentHashMap 的关键区别
相比 ConcurrentHashMap,synchronizedMap 的设计更简单但扩展性差:
- 所有操作串行执行,吞吐量随线程数增加而下降
- 不支持高并发下的分段锁或 CAS 操作
- 没有
computeIfAbsent等原子复合方法 - 适用于轻量级、低并发或遗留系统改造场景
使用建议:什么情况下该选它?
它适合这些情况:
- 已有非线程安全 map,需要快速加一层同步保障
- 并发写操作极少,主要做读取或偶尔更新
- 不需要高级并发语义(如弱一致性遍历、批量原子操作)
- 项目受限于 JDK 版本(比如老系统还在用 Java 7),无法用
ConcurrentHashMap的新特性
如果业务明确要求高并发读写,优先考虑 ConcurrentHashMap 或根据场景选用 CopyOnWriteArrayList 风格结构。

















