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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值