Collections.synchronizedList仅保证单个操作线程安全,复合操作和迭代需手动同步;替代方案有CopyOnWriteArrayList、ConcurrentLinkedQueue等,应依读写比例与场景选择。

直接用 Collections.synchronizedList 包装原始列表即可,但要注意它只保证单个操作的线程安全,复合操作仍需手动同步。
基本用法:包装已有列表
传入一个非线程安全的列表(如 ArrayList 或 LinkedList),返回一个线程安全的代理列表:
List<String> list = new ArrayList<>(); List<String> syncList = Collections.synchronizedList(list);
此后所有通过 syncList 进行的 add、get、remove 等单步操作都是同步的。
必须手动同步的复合操作
像“检查后执行”这类多步操作(例如先判断是否为空再取首元素)不是原子的,即使用了 synchronizedList 也会出错:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ❌ 错误写法(竞态条件):
if (!syncList.isEmpty()) { String first = syncList.get(0); // 可能在 isEmpty() 后、get() 前被其他线程清空 } - ✅ 正确写法(显式加锁):
synchronized (syncList) { if (!syncList.isEmpty()) { String first = syncList.get(0); // 安全操作 } }
迭代器仍需外部同步
synchronizedList 返回的迭代器本身不加锁,遍历时必须用同步块包裹:
synchronized (syncList) {
for (String s : syncList) { // 内部使用迭代器,必须同步
System.out.println(s);
}
}
否则可能抛出 ConcurrentModificationException 或读到不一致状态。
替代方案考虑
如果需要更高并发性能或更丰富的线程安全操作,可考虑:
-
CopyOnWriteArrayList:适合读多写少、迭代频繁的场景 -
ConcurrentLinkedQueue或BlockingQueue实现:适用于队列类操作 - 手动使用
ReentrantLock或synchronized控制更细粒度逻辑
不要仅因“线程安全”就默认选 synchronizedList,要结合实际读写比例和操作模式选择。

















