Collections.synchronizedList() 是 Java 提供的一种 线程安全包装器 ,用于给普通的 List(例如 ArrayList、LinkedList)加上一层 同步(synchronized)保护。
一、基本用法
java
List<Integer> list = new ArrayList<>();
List<Integer> syncList = Collections.synchronizedList(list);
这样得到的 syncList 是一个 线程安全 的 List,在多线程场景下可以安全地增删改查。
二、源码解析(JDK 8)
来看 Collections 类的实现:
java
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
如果底层 list 是随机访问的(例如 ArrayList),则返回 SynchronizedRandomAccessList;
否则返回 SynchronizedList。这两个类结构几乎一样,都是对原 List 加锁包装。
关键类结构(内部静态类):
java
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
public void add(int index, E element) {
synchronized (mutex) {
list.add(index, element);
}
}
public E get(int index) {
synchronized (mutex) {
return list.get(index);
}
}
// 其他方法都加 synchronized(mutex)
}
三、执行流程说明
以 add() 为例:
java
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
syncList.add(1);
执行过程:
1️⃣ 创建时,synchronizedList() 会把你的 ArrayList 包装成 SynchronizedList 对象。
2️⃣ 内部有一个共享锁对象 mutex(通常就是 this)。
3️⃣ 每次对 list 的操作(如 add()、get()、remove())都包裹在 synchronized (mutex) 块中。
4️⃣ 从而保证同一时间只有一个线程能访问这个列表。
四、和 CopyOnWriteArrayList 的区别
| 对比项 | Collections.synchronizedList() |
CopyOnWriteArrayList |
|---|---|---|
| 实现方式 | 在每个方法外层加 synchronized 锁 |
写时复制:写操作复制新数组 |
| 读性能 | 所有操作都需加锁,读性能较低 | 读操作无锁,非常快 |
| 写性能 | 写锁竞争严重(串行化) | 写时复制成本高(需要复制整个数组) |
| 适用场景 | 写多读少 | 读多写少 |
| 迭代器行为 | 迭代时需要手动同步,否则可能抛异常 | 迭代是快照,不受修改影响 |
| 底层存储 | 原 List 对象 |
内部 volatile Object[] array |
✅ 五、使用迭代器的注意事项
java
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
// 迭代时要手动加锁
synchronized (syncList) {
for (Integer i : syncList) {
System.out.println(i);
}
}
否则,多个线程同时迭代和修改时,可能导致 ConcurrentModificationException。
✅ 六、小结
| 特性 | synchronizedList | CopyOnWriteArrayList |
|---|---|---|
| 加锁机制 | 整体锁(synchronized) | 写时复制(volatile + CAS) |
| 读性能 | 慢(加锁) | 快(无锁) |
| 写性能 | 中(锁竞争) | 慢(复制数组) |
| 一致性 | 强一致 | 最终一致(读快照) |
| 使用场景 | 写多读少 | 读多写少 |