您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

java并发包之CopyOnWriteArrayList源码分析

大多数情况下读操作是远远大于写操作的,读操作本身不会修改集合中的数据,所以说读操作和写操作一样加锁的话对资源是一种极大的浪费。而java.util.concurrent包刚好为我们提供了一种读不加锁写加锁的集合,而且读写不互斥,只有写写之间才会阻塞,让我们在构建多线程的应用时,既保证了运行效率,又保证了数据的一致性,废话不多说,我们直接开撸源码。

首先是属性,CopyOnWriteArrayList重要的属性比较少:

    /** 保护所有并发资源的可重入锁 */
    final transient ReentrantLock lock = new ReentrantLock();

    /** 集合底层的对象数组,只能通过getArray/setArray访问 */
    private transient volatile Object[] array;
    
    /** 调用native方法的UNSAFE类 */
    private static final sun.misc.Unsafe UNSAFE;
    
    /** 集合的锁属性相对于集合对象在内存中起始地址的偏移量 */
    private static final long lockOffset;

读数据的get(int index)函数

    /**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        return get(getArray(), index);
    }

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

可以看到实现非常简单,直接返回数组中参数下标对应的元素。

重点在于写操作,下面来看add(E e)函数


    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        //拿到锁对象
        final ReentrantLock lock = this.lock;
        //加锁
        lock.lock();
        try {
            //局部变量储存数组
            Object[] elements = getArray();
            int len = elements.length;
            //拷贝出来一份新数组
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            //在新数组进行赋值操作
            newElements[len] = e;
            //赋值给成员变量的数组
            setArray(newElements);
            return true;
        } finally {
            //释放锁
            lock.unlock();
        }
    }

CopyOnWriteArrayList 类的所有可变操作(add,set等等)都是通过创建底层数组的新副本来实现的。当 List 需要被修改的时候,并不直接修改原有数组对象,而是对原有数据进行一次拷贝,将修改的内容写入副本中。写完之后,再将修改完的副本替换成原来的数据,这样就可以保证写操作不会影响读操作了。

从 CopyOnWriteArrayList 的名字可以看出,CopyOnWriteArrayList 是满足 CopyOnWrite 的 ArrayList,所谓 CopyOnWrite 的意思:、就是对一块内存进行修改时,不直接在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后,再将原来指向的内存指针指到新的内存,原来的内存就可以被回收。


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进