编程语言
首页 > 编程语言> > 深入分析CopyOnWriteArrayList的源码设计

深入分析CopyOnWriteArrayList的源码设计

作者:互联网

深入分析CopyOnWriteArrayList的源码设计

CopyOnWriteArrayList提供线程安全性和可伸缩性

可伸缩性指的是一个应用程序在工作负载和可用处理资源增加时其吞吐量的表现情况。

一个可伸缩的程序能够通过使用更多的处理器、内存或者I/O带宽来相应地处理更大的工作负载。

锁住某个共享的资源以获得独占式的访问这种做法会形成可伸缩性瓶颈――它使其他线程不能访问那个资源,即使有空闲的处理器可以调用那些线程也无济于事**。为了取得可伸缩性,我们必须消除或者减少我们对独占式资源锁的依赖。**

CopyOnWriteArrayList

​ CopyOnWriteArrayList是java1.5版本提供的一个线程安全的ArrayList变体,ArrayList具有fast-fail特性,它是值在遍历过程中,如果ArrayList的内容发生过修改,那么会抛出ConcurrentModificationException。

​ 在多线程环境下,这种情况变得尤为突出。不使用迭代器形式而使用下标来遍历就会带来一个问题,读写没有分离。写操作户影响到读的准确性,甚至导致IndexOutOfBoundsException。不直接遍历list,而是把list拷贝一份数组,再行遍历。

​ 写时拷贝,自然实在做写操作时,把原始数据拷贝到一个新的数组,与写操作相关的主要有三个方法:add、remove、set,在每一次add操作里,数组都被拷贝了一个副本,这就是写时拷贝的原理,那么写时拷贝和读时拷贝各有什么优势,如何选择呢?

​ 如果一个list的遍历操作比写入操作更频繁,那么用该使用CopyOnWriteArrayList,如果list的写入操作比遍历操作更频繁,那么应该考虑读时拷贝。

CopyOnWriteArrayList源码原理分析

1 使用场景

2 读写规则

/**
 * CopyOnWriteArrayList可以在迭代中修改数组内容,而ArrayList不行
 * @author yiren
 */
public class CopyOnWriteArrayListExample01 {
    public static void main(String[] args) {
        // ArrayList<String> list = new ArrayList<>();
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(list);
            String next = iterator.next();
            System.out.println(next);

            if (next.equals("2")) {
                list.remove("3");
            }

            if (next.equals("4")) {
                list.add("3 add");
            }
        }
    }
}

[1, 2, 3, 4, 5]
1
[1, 2, 3, 4, 5]
2
[1, 2, 4, 5]
3
[1, 2, 4, 5]
4
[1, 2, 4, 5, 3 add]
5

Process finished with exit code 0

3 实现原理

/**
 * @author yiren
 */
public class CopyOnWriteArrayListExample02 {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        list.add("1");
        list.add("2");
        list.add("3");
        Iterator<String> itr1 = list.iterator();
        list.add("4");
        Iterator<String> itr2 = list.iterator();

        itr1.forEachRemaining(System.out::print);
        System.out.println();
        itrforEachRemaining(System.out::print);
    }
}

123
1234
Process finished with exit code 0

4 存在的缺点

5 源码分析

    private transient volatile Object[] array;

    /** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();

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

    public CopyOnWriteArrayList(Collection<? extends E> c) {
        Object[] elements;
        if (c.getClass() == CopyOnWriteArrayList.class)
            elements = ((CopyOnWriteArrayList<?>)c).getArray();
        else {
            elements = c.toArray();
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elements.getClass() != Object[].class)
                elements = Arrays.copyOf(elements, elements.length, Object[].class);
        }
        setArray(elements);
    }


    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        //添加的时候先上锁
        lock.lock();
        try {
            // copy一份到新数组,数组长度+1
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            // 新值放到末尾,把指针指过去
            newElements[len] = e;
            // 最后返回true 并释放锁
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

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

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


标签:elements,迭代,ArrayList,list,CopyOnWriteArrayList,add,源码,深入分析
来源: https://blog.csdn.net/fly910905/article/details/122785776