collections.synchronizedcollection 是 java 提供的轻量级线程安全包装工具,它通过同步装饰使单方法调用具备原子性,但需配合 final 声明、禁止原始引用泄露、遍历时显式加锁或快照复制、复合操作整体同步等规范使用,否则仍存在并发风险。

Collections.synchronizedCollection 是 Java 提供的轻量级线程安全包装工具,它不创建新集合,而是对已有 Collection 实例加一层同步装饰——所有公开方法(add、remove、contains、size 等)自动持锁执行,单操作具备原子性。但它不是“开箱即用”的完全安全方案,需配合正确用法才能规避并发陷阱。
核心使用方式与初始化规范
调用方式简洁,但初始化方式直接影响安全性:
- 推荐写法:直接包装匿名实例,避免原始引用泄露
Collection<string> safeColl = Collections.synchronizedCollection(new ArrayList());</string> - 必须声明为 final,防止被重新赋值或暴露底层集合
private final Collection<string> safeColl = Collections.synchronizedCollection(new LinkedList());</string> - 禁止保留并操作原始集合(如 new ArrayList() 后又单独用它),否则同步失效
- 不要对返回的同步集合调用
subList()、Arrays.asList()或传给 stream() 的中间操作,这些视图不继承同步行为
遍历必须显式加锁,否则必抛异常
该方法不包装迭代器,iterator() 返回的是原始集合的迭代器,无任何同步逻辑。增强 for 循环本质调用 iterator(),若遍历时有其他线程修改集合,100% 触发 ConcurrentModificationException。
- 安全遍历方式一(同步块包裹整个循环):
synchronized (safeColl) {<br> for (String s : safeColl) { /* 安全处理 */ }<br>} - 安全遍历方式二(快照复制,推荐读多场景):
List<string> snapshot = new ArrayList(safeColl);<br>for (String s : snapshot) { /* 处理副本,原集合可并发修改 */ }</string> - 避免在 synchronized 块内执行耗时操作(如 I/O、远程调用),以防锁持有过久阻塞其他线程
复合操作必须整体同步,单方法安全 ≠ 业务逻辑安全
添加、删除、查询各自是线程安全的,但多个方法组合成的业务逻辑(如“检查不存在再添加”)存在竞态窗口,必须由外部同步保障原子性。
- 错误写法(两步之间可能被插队):
if (!safeColl.contains("x")) safeColl.add("x"); // 可能重复 - 正确写法(整个判断+动作包进同步块):
synchronized (safeColl) {<br> if (!safeColl.contains("x")) {<br> safeColl.add("x");<br> }<br>} - 类似场景还包括:
if (!safeColl.isEmpty()) safeColl.iterator().next();→ 判空后取首元素前集合可能已空,必须同步包裹
适用场景与替代建议
它适合低并发、读写频率接近、且逻辑简单明确的场景;不适合高吞吐写操作或复杂迭代逻辑。
- 优势:零依赖、API 简洁、内存开销小、与原有 Collection 接口完全兼容
- 劣势:全局锁粒度粗,写竞争激烈时性能急剧下降;无法规避复合操作风险;不支持批量原子操作(如 removeAllIf)
- 替代方案参考:
• 读远多于写的场景 →CopyOnWriteArrayList(无锁读,写复制)
• 高并发 Map 操作 →ConcurrentHashMap(分段/无锁优化)
• 需要强一致性且逻辑复杂 → 直接使用java.util.concurrent中的专用并发集合
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











