Skip to content
进阶

一句话答案

写时复制:读无锁直接读数组,写加锁复制新数组修改后替换原数组,适合读多写少场景(如监听器列表)。

核心要点

核心原理:

  • :无锁,直接读取内部 Object[] array(volatile 保证可见性)
  • :加 ReentrantLock → 复制底层数组 → 修改副本 → 替换原数组 → 释放锁
java
public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] old = getArray();
        Object[] newArr = Arrays.copyOf(old, old.length + 1);
        newArr[old.length] = e;
        setArray(newArr);  // volatile 写
        return true;
    } finally { lock.unlock(); }
}

优缺点:

  • ✅ 读无锁,并发读性能极高
  • ✅ 迭代器不会抛 ConcurrentModificationException
  • ❌ 写操作慢(复制整个数组)
  • ❌ 内存占用(写时两份数组)
  • ❌ 数据弱一致性(读到旧数据)

适用场景: 事件监听器列表、配置项缓存(读远多于写)

追问与易错

追问方向:

  • 写时复制的内存开销大吗?
  • 迭代器是强一致还是弱一致?
  • 什么场景适合用?

易错点:

  • ❌ 写也是 O(1)——每次写复制整个数组 O(n)
  • ❌ 在写多场景使用——性能极差

💡 记忆锚点

写时复制就像公告栏:读的人随便看不用排队,改的人先复印一份公告在副本上修改,改好后一次性换上去。代价是每次修改都要复印整张纸——所以只适合"看的人多、改的人少"的场景。