CopyOnWriteArrayList底层原理全面解析【建议收藏】

简介

CopyOnWriteArrayList是Java中的一个线程安全的集合类,是ArrayList线程安全版本,主要通过Copy-On-Write(写时复制,简称COW)机制来保证线程安全。

Copy-On-Write机制核心思想:向一个数组中添加数据时,不直接操作原始数组,而是拷贝原始数组生成一份原始数组副本,将需要添加的数据添加到原始数组副本中,操作完成后再用原始数组副本直接替换原始数组,从而保证多个线程同时操作原始数组时的线程安全。

应用场景

CopyOnWriteArrayList的主要应用场景:

  • 读多写少的场景,CopyOnWriteArrayList允许多个线程同时对数据进行读操作,但同一时刻只允许一个线程对数据进行写操作,并且进行写操作时需要复制原始数据的副本,造成空间和时间的浪费。
  • 允许读写数据时出现短暂不一致的场景,CopyOnWriteArrayList写操作完成后,需要使用更新后的数据副本替换原始数据,有可能使CopyOnWriteArrayList中的数据出现短暂不一致。

实现原理

CopyOnWriteArrayList类的继承关系:

CopyOnWriteArrayList类继承关系图

  • Iterable接口CopyOnWriteArrayList类实现了Iterable接口,使得它可以被迭代遍历。通过实现iterator()方法,可以获取一个迭代器,用于遍历集合中的元素。

  • Collection接口CopyOnWriteArrayList类继承了AbstractCollection类,间接实现了Collection接口。通过实现Collection接口,CopyOnWriteArrayList类获得了一些常用的集合操作方法,比如判断是否包含某个元素、计算集合的大小等。

  • List接口CopyOnWriteArrayList类间接实现了List接口,通过继承AbstractList类实现了List接口的一些方法。List接口定义了有序的集合,CopyOnWriteArrayList类通过继承List接口,可以按照索引进行访问和操作集合中的元素。

  • Cloneable接口CopyOnWriteArrayList类实现了Cloneable接口,使得它可以进行克隆操作。通过实现clone()方法,可以创建CopyOnWriteArrayList对象的副本。

  • Serializable接口CopyOnWriteArrayList类实现了Serializable接口,使得它可以进行序列化操作。通过实现writeObject()readObject()方法,可以将CopyOnWriteArrayList对象转换为字节流,并进行存储或传输。

  • RandomAccess接口CopyOnWriteArrayList类实现了RandomAccess接口,表示它可以高效地随机访问元素。RandomAccess接口是一个标记接口,用于标识实现该接口的类可以通过索引进行快速随机访问,CopyOnWriteArrayList类通过实现该接口,表明它可以高效地随机访问元素。

重要属性

CopyOnWriteArrayList类中有两个重要的属性:

  • array:Object数组:用于存储CopyOnWriteArrayList中的数据。该属性使用transient和volatile关键字进行修饰:

    transient:表示序列化CopyOnWriteArrayList对象时,array属性不会被自动序列化。

    volatile:表示一个线程对CopyOnWriteArrayList数据的更新操作,对其他线程可见。

  • lock:ReentrantLock锁:用于保证多个线程同时对CopyOnWriteArrayList进行写操作的线程安全性。该属性也使用transient关键字进行修饰。

CopyOnWriteArrayList类定义代码如下:

public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
   
   
    ...
    // ReentrantLock锁
    final transient ReentrantLock lock = new ReentrantLock();
    // Object数组
    private transient volatile Object[] array;
    ...
}

构造函数

CopyOnWriteArrayList的构造函数:

/**
 * 无参构造函数
 */
public CopyOnWriteArrayList() {
   
   
    // 创建Object数组
    setArray(new Object[0]);
}
/**
 * 有参构造函数
 * c:集合
 */
public CopyOnWriteArrayList(Collection<? extends E> c) {
   
   
    Object[] elements;
    // 如果参数c为CopyOnWriteArrayList对象,则将c中的数组直接赋值给elements数组
    if (c.getClass() == CopyOnWriteArrayList.class)
        elements = ((CopyOnWriteArrayList<?>)c).getArray();
    else {
   
   
        // 将参数c转换为数组并赋值给elements数组
        elements = c.toArray();
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        // 如果数组(c)的类型不是Object[],则将数组(c)中的元素复制给Object数组,再将Object数组赋值给elements数组
        if (elements.getClass() != Object[].class)
            elements = Arrays.copyOf(elements, elements.length, Object[].class);
    }
    // 将CopyOnWriteArrayList的array属性指向elements数组
    setArray(elements);
}
/**
 * 有参构造函数
 * toCopyIn:数组
 */
public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小Java开发者

“是一种鼓励,你懂的”

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值