Collections.synchronizedMap通过synchronized关键字为普通Map提供线程安全,适用于读多写少场景,但遍历时需手动加锁,且性能较低,高并发下推荐使用ConcurrentHashMap。

在多线程环境下操作Map时,如果使用普通的HashMap可能会导致数据不一致或并发修改异常。Java提供了多种方式来保证Map的线程安全,其中一种经典方法是使用 Collections.synchronizedMap 来包装普通Map,使其具备基本的线程安全性。
什么是 Collections.synchronizedMap
该方法属于 java.util.Collections 工具类,用于将一个非线程安全的 Map 包装成线程安全的版本。它通过在每个公共方法上加 synchronized 关键字,确保同一时刻只有一个线程可以访问 Map 的某个方法。基本用法如下:
Mapmap = new HashMap<>(); Map syncMap = Collections.synchronizedMap(map);
也可以直接写成一行:
MapsyncMap = Collections.synchronizedMap(new HashMap ());
遍历时必须手动同步
虽然 synchronizedMap 的每一个单独操作(如 get、put、remove)是线程安全的,但复合操作(尤其是迭代)仍然需要外部同步,否则可能抛出 ConcurrentModificationException 或读取到不一致的数据。正确遍历方式如下:
立即学习“Java免费学习笔记(深入)”;
Map如果不加 synchronized 块,即使 map 是 synchronizedMap,也有可能在迭代过程中被其他线程修改,导致异常。syncMap = Collections.synchronizedMap(new HashMap ()); // 遍历时必须使用同步块 synchronized (syncMap) { for (Map.Entry entry : syncMap.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } }
适用场景与局限性
synchronizedMap 适合读多写少的并发场景,它的实现简单,兼容所有 Map 实现。但由于整个 Map 使用同一个锁,写操作会阻塞所有其他读写线程,性能较低,不适合高并发写入环境。- 优点:使用简单,适用于轻量级并发控制。
- 缺点:性能较差,所有方法共用一个锁;迭代需额外同步;不支持高效并发访问。
常见使用技巧
为了更安全地使用 synchronizedMap,注意以下几点:- 始终对复合操作(如检查再插入、循环遍历)加 synchronized 同步块。
- 避免长时间持有 map 锁,减少同步代码块范围。
- 不要在同步块中执行耗时操作(如网络调用、文件读写),以免阻塞其他线程。
- 考虑使用 Map 的不可变副本进行遍历,减轻锁竞争。
示例:安全地检查并添加元素
synchronized (syncMap) {
if (!syncMap.containsKey("key1")) {
syncMap.put("key1", 100);
}
}
基本上就这些。Collections.synchronizedMap 能快速为 Map 提供线程安全能力,但要注意其同步限制和性能瓶颈。合理使用同步块,才能真正保障多线程下的数据一致性。









