返回

拆解技术核心,庖丁CopyOnWriteArrayList

后端

剖析CopyOnWriteArrayList的内部机理

CopyOnWriteArrayList是一个线程安全的List接口实现类,与ArrayList相比,它具有以下特点:

  • CopyOnWriteArrayList的读操作是线程安全的,这意味着多个线程可以同时读取列表中的元素,而不会出现数据不一致的情况。
  • CopyOnWriteArrayList的写操作是线程不安全的,这意味着当一个线程正在写入列表时,其他线程不能同时写入列表,否则会出现数据不一致的情况。
  • CopyOnWriteArrayList使用了一种称为“写时复制”的机制来保证线程安全。当一个线程要写入列表时,它会先复制一份列表,然后在复制的列表上进行写入操作,最后将复制的列表替换原有的列表。这样,即使在写入过程中其他线程也在读取列表,也不会出现数据不一致的情况。

深入CopyOnWriteArrayList的源代码

CopyOnWriteArrayList的源代码相对简单,但它却巧妙地实现了线程安全。下面我们来看看它的源代码:

import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.RandomAccess;
import java.util.concurrent.locks.ReentrantLock;

public class CopyOnWriteArrayList<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, Serializable {

    private static final long serialVersionUID = 8683459283918986980L;

    final transient ReentrantLock lock = new ReentrantLock();
    private transient volatile Object[] elements;

    public CopyOnWriteArrayList() {
        this(10);
    }

    public CopyOnWriteArrayList(int initialCapacity) {
        elements = new Object[initialCapacity];
    }

    public CopyOnWriteArrayList(Collection<? extends E> c) {
        elements = c.toArray();
    }

    // ... 省略其他代码 ...
}

从源代码可以看出,CopyOnWriteArrayList是一个内部使用ReentrantLock锁来实现线程安全的数据结构。它使用了一个volatile修饰的Object数组elements来存储数据,数组中的元素都是不可变的。当一个线程要写入列表时,它会先获取锁,然后复制一份elements数组,在复制的数组上进行写入操作,最后将复制的数组替换原有的elements数组。这样,即使在写入过程中其他线程也在读取列表,也不会出现数据不一致的情况。

总结

CopyOnWriteArrayList是一种线程安全的List接口实现类,它通过使用“写时复制”的机制来保证线程安全。CopyOnWriteArrayList的源代码相对简单,但它却巧妙地实现了线程安全,这使得它成为多线程环境下处理数据的一种非常有效的工具。