CopyOnWriteArrayList源码分析

前两天刚分析完了ArrayList,趁热打铁,接着来看CopyOnWriteArrayList。
CopyOnWriteArrayList与ArrayList大部分的实现都是类似,只是在ArrayList的基础上加上了一个锁对象,对所有改变集合数据结构的操作加了同步代码块,现在的synchronized不再是之前那个稳定不变的mutex_lock重量级锁,而是借助mark_word等,在并发情况逐步升级锁,单线程情况就算加了synchronized关键字,性能就跟没写差不多。

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8673264195747942595L;

    final transient Object lock = new Object();

    private transient volatile Object[] elements;

    final Object[] getArray() {
        return elements;
    }

    final void setArray(Object[] a) {
        elements = a;
    }


    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

CopyOnWriteArrayList最大的特点就是"写时复制"。集合结构发生改变是先获取object 的锁,复制出一个新的数组,在新数组上进行操作,之后把新数组赋值给集合的数据字段,释放锁。 可以想到高并发的情况下,多个线程同时修改结构的操作是要竞争锁,但是同时的读取数据就没问题。实现的是读写分离,读在老数据上,写在新数据上,最后新数据数组覆盖老的。
读操作无须加锁,

   // Positional Access Operations
    @SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    static String outOfBounds(int index, int size) {
        return "Index: " + index + ", Size: " + size;
    }

    public E get(int index) {
        return get(getArray(), index);
    }

写操作在新数组上操作,setArray 覆盖老数组。

 public E set(int index, E element) {
        synchronized (lock) {
            Object[] elements = getArray();
            E oldValue = get(elements, index);
            if (oldValue != element) {
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len);
                newElements[index] = element;
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        }
    }

    public boolean add(E e) {
        synchronized (lock) {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        }
    }

    final void setArray(Object[] a) {
        elements = a;
    }

Arrays.copyOf 生成一个新的数组,并且复制原数据。


  public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }



  public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CopyOnWriteArrayList 是 Java 中的一个线程安全的集合类,它的实现原理是在写操作时创建一个新的数组来存储数据,从而实现了读写分离,保证了读操作的线程安全性。 具体的实现原理如下: 1. CopyOnWriteArrayList 内部使用一个数组来存储数据。 2. 在进行写操作(添加、修改、删除)时,先创建一个新的数组,将原数组的数据复制到新数组中,并在新数组上进行写操作。 3. 写操作完成后,将新数组赋值给原数组,从而实现了数据的更新。 4. 在进行读操作时,直接读取原数组的数据,保证了读操作的线程安全性。 CopyOnWriteArrayList 的实现原理保证了读操作的线程安全性,因为读操作不会对原数组进行修改,而是读取原数组的数据。但是写操作会创建一个新的数组,因此写操作的性能相对较低。 范例:<<引用[1]:CopyOnWriteArrayList原理。 文章目录 一、 CopyOnWriteArrayList介绍二、 CopyOnWriteArrayList原理三、 CopyOnWriteArrayList 属性介绍四、 构造器以及添加add方法五、 get(int index)六、 remove(int index)七、 遍历 。 引用:CopyOnWriteArrayList实现原理及源码分析。1 List list = Collections.synchronizedList(new ArrayList()); 。 CopyOnWriteArrayList 实现原理如下: 1. 内部使用一个数组来存储数据。 2. 在进行写操作时,先创建一个新的数组,将原数组的数据复制到新数组中,并在新数组上进行写操作。 3. 写操作完成后,将新数组赋值给原数组,从而实现了数据的更新。 4. 在进行读操作时,直接读取原数组的数据,保证了读操作的线程安全性。 5. 写操作会创建一个新的数组,因此写操作的性能相对较低。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值