zoukankan      html  css  js  c++  java
  • CopyOnWriteArrayList源码浅析(基于jdk1.8.0_231)

    1. CopyOnWriteArrayList 简介

    • CopyOnWriteArrayList是ArrayList线程安全的替代品;
    • 值得注意的是,CopyOnWriteArrayList对其结构的修改操作都是在一个拷贝原数组的快照上进行的,这样虽然有一定的空间代价,但是可以将对原数组的“读写分离”,特别是,迭代和反复添加元素并发进行时,不需要考虑ConcurrentModificationException异常;
    • 使用迭代器迭代时,首先会记录当前一个当前list的快照snapshot,别的线程对list的修改不影响迭代(是对复制的原数组的修改);
    • CopyOnWriteArrayList直接实现了List, RandomAccess, Cloneable, java.io.Serializable的接口;
    • CopyOnWriteArrayList 比较合适在多线程 “读多写少”的环境,读的操作都是无锁的,效率较高
    • 可以存入null;

    2. CopyOnWriteArrayList UML

    3. CopyOnWriteArrayList 源码浅析

    package java.util.concurrent;
    import java.util.AbstractList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Comparator;
    import java.util.ConcurrentModificationException;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ListIterator;
    import java.util.NoSuchElementException;
    import java.util.Objects;
    import java.util.RandomAccess;
    import java.util.Spliterator;
    import java.util.Spliterators;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    import java.util.function.UnaryOperator;
    import sun.misc.SharedSecrets;
    
    /**
     * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
     * operations ({@code add}, {@code set}, and so on) are implemented by
     * making a fresh copy of the underlying array.
     *
     * <p>This is ordinarily too costly, but may be <em>more</em> efficient
     * than alternatives when traversal operations vastly outnumber
     * mutations, and is useful when you cannot or don't want to
     * synchronize traversals, yet need to preclude interference among
     * concurrent threads.  The "snapshot" style iterator method uses a
     * reference to the state of the array at the point that the iterator
     * was created. This array never changes during the lifetime of the
     * iterator, so interference is impossible and the iterator is
     * guaranteed not to throw {@code ConcurrentModificationException}.
     * The iterator will not reflect additions, removals, or changes to
     * the list since the iterator was created.  Element-changing
     * operations on iterators themselves ({@code remove}, {@code set}, and
     * {@code add}) are not supported. These methods throw
     * {@code UnsupportedOperationException}.
     *
     * <p>All elements are permitted, including {@code null}.
     *
     * <p>Memory consistency effects: As with other concurrent
     * collections, actions in a thread prior to placing an object into a
     * {@code CopyOnWriteArrayList}
     * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
     * actions subsequent to the access or removal of that element from
     * the {@code CopyOnWriteArrayList} in another thread.
     *
     * <p>This class is a member of the
     * <a href="{@docRoot}/../technotes/guides/collections/index.html">
     * Java Collections Framework</a>.
     *
     * @since 1.5
     * @author Doug Lea
     * @param <E> the type of elements held in this collection
     */
    public class CopyOnWriteArrayList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
        private static final long serialVersionUID = 8673264195747942595L;
        // 初始化可重入锁
        final transient ReentrantLock lock = new ReentrantLock();
        // 存数据的数组,仅可通过getArray/setArray 返回
        private transient volatile Object[] array;
        final Object[] getArray() {
            return array;
        }
        final void setArray(Object[] a) {
            array = a;
        }
        // 创建空list
        public CopyOnWriteArrayList() {
            setArray(new Object[0]);
        }
        // 用一个具体的集合c填充list,其中但c=null时,NullPointerException
        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);
        }
    
        // 拷贝toCopyIn作为list
        public CopyOnWriteArrayList(E[] toCopyIn) {
            setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
        }
    
        //返回列表中元素的数量
        public int size() {
            return getArray().length;
        }
        public boolean isEmpty() {
            return size() == 0;
        }
        private static boolean eq(Object o1, Object o2) {
            return (o1 == null) ? o2 == null : o1.equals(o2);
        }
    
        // static版本的indexOf 
        private static int indexOf(Object o, Object[] elements,
                                   int index, int fence) {
            if (o == null) {
                for (int i = index; i < fence; i++)
                    if (elements[i] == null)
                        return i;
            } else {
                for (int i = index; i < fence; i++)
                    if (o.equals(elements[i]))
                        return i;
            }
            return -1;
        }
        // static版本的lastIndexOf 
        private static int lastIndexOf(Object o, Object[] elements, int index) {
            if (o == null) {
                for (int i = index; i >= 0; i--)
                    if (elements[i] == null)
                        return i;
            } else {
                for (int i = index; i >= 0; i--)
                    if (o.equals(elements[i]))
                        return i;
            }
            return -1;
        }
        public boolean contains(Object o) {
            Object[] elements = getArray();
            return indexOf(o, elements, 0, elements.length) >= 0;
        }
    
        /**
         * {@inheritDoc}
         */
        public int indexOf(Object o) {
            Object[] elements = getArray();
            return indexOf(o, elements, 0, elements.length);
        }
    
        public int indexOf(E e, int index) {
            Object[] elements = getArray();
            return indexOf(e, elements, index, elements.length);
        }
    
        /**
         * {@inheritDoc}
         */
        public int lastIndexOf(Object o) {
            Object[] elements = getArray();
            return lastIndexOf(o, elements, elements.length - 1);
        }
        public int lastIndexOf(E e, int index) {
            Object[] elements = getArray();
            return lastIndexOf(e, elements, index);
        }
        //返回list的浅拷贝
        public Object clone() {
            try {
                @SuppressWarnings("unchecked")
                CopyOnWriteArrayList<E> clone =
                    (CopyOnWriteArrayList<E>) super.clone();
                clone.resetLock();
                return clone;
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError();
            }
        }
        // list 数组化
        public Object[] toArray() {
            Object[] elements = getArray();
            return Arrays.copyOf(elements, elements.length);
        }
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T a[]) {
            Object[] elements = getArray();
            int len = elements.length;
            if (a.length < len)
                return (T[]) Arrays.copyOf(elements, len, a.getClass());
            else {
                System.arraycopy(elements, 0, a, 0, len);
                if (a.length > len)
                    a[len] = null;
                return a;
            }
        }
    
        // Positional Access Operations
    
        @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);
        }
    
        public E set(int index, E element) {
            final ReentrantLock lock = this.lock;
            lock.lock();  //加锁
            try {
                Object[] elements = getArray();
                E oldValue = get(elements, index);  //得到index位置的old value
                if (oldValue != element) {  //如果 oldValue != element
                    int len = elements.length;
                    Object[] newElements = Arrays.copyOf(elements, len); //将元素组拷贝至新数组
                    newElements[index] = element;  // 修改新数组
                    setArray(newElements);  // 将array 指向 新数组
                } else {
                    // Not quite a no-op; ensures volatile write semantics
                    setArray(elements);  //oldvalue == element 没得改
                }
                return oldValue;
            } finally {
                lock.unlock();  //解锁
            }
        }
    
        public boolean add(E e) {
            final ReentrantLock lock = this.lock; //先得到类的ReentrantLock lock
            lock.lock(); // 加锁
            try {
                Object[] elements = getArray();
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len + 1); // 多拷贝一个位置
                newElements[len] = e;  // add
                setArray(newElements);
                return true;
            } finally {
                lock.unlock(); //解锁
            }
        }
    
        public void add(int index, E element) {
            final ReentrantLock lock = this.lock;
            lock.lock();  // 加锁
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (index > len || index < 0)
                    throw new IndexOutOfBoundsException("Index: "+index+
                                                        ", Size: "+len);
                Object[] newElements;
                int numMoved = len - index; 
                if (numMoved == 0)
                    newElements = Arrays.copyOf(elements, len + 1); // 拷贝原数组
                else {
                    newElements = new Object[len + 1];
                    System.arraycopy(elements, 0, newElements, 0, index);
                    System.arraycopy(elements, index, newElements, index + 1,
                                     numMoved);
                }
                newElements[index] = element;
                setArray(newElements);
            } finally {
                lock.unlock(); //解锁
            }
        }
    
        public E remove(int index) {
            final ReentrantLock lock = this.lock;
            lock.lock(); //加锁
            try {
                Object[] elements = getArray();
                int len = elements.length;
                E oldValue = get(elements, index);
                int numMoved = len - index - 1; 
                if (numMoved == 0) //如果移除是第一个元素
                    setArray(Arrays.copyOf(elements, len - 1));
                else {   //移除的中间元素
                    Object[] newElements = new Object[len - 1];  //先开个新数组
                    System.arraycopy(elements, 0, newElements, 0, index);
                    System.arraycopy(elements, index + 1, newElements, index,
                                     numMoved);
                    setArray(newElements);
                }
                return oldValue;
            } finally {
                lock.unlock(); //解锁
            }
        }
    
        
        public boolean remove(Object o) {
            Object[] snapshot = getArray(); 
            int index = indexOf(o, snapshot, 0, snapshot.length); //得到o第一次出现的索引
            return (index < 0) ? false : remove(o, snapshot, index); //移除
        }
        private boolean remove(Object o, Object[] snapshot, int index) { 
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] current = getArray(); //current = array
                int len = current.length; //array.length
                if (snapshot != current)
                    findIndex: {  // 牛逼哄哄的样子,break执行时,跳到这,就是goto哦,不过大佬都喜欢这么写,类库中很多这样的代码
                    int prefix = Math.min(index, len);  
                    for (int i = 0; i < prefix; i++) {
                        if (current[i] != snapshot[i] && eq(o, current[i])) {
                            index = i; 
                            break findIndex;
                        }
                    }
                    if (index >= len)
                        return false;
                    if (current[index] == o)
                        break findIndex;
                    index = indexOf(o, current, index, len); 
                    if (index < 0)
                        return false;
                }
                Object[] newElements = new Object[len - 1];
                System.arraycopy(current, 0, newElements, 0, index);
                System.arraycopy(current, index + 1,
                                 newElements, index,
                                 len - index - 1);
                setArray(newElements);
                return true;
            } finally {
                lock.unlock(); //解锁
            }
        }
    
        //把[fromIndex,toIndex)之间的元素都移除掉
        void removeRange(int fromIndex, int toIndex) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
    
                if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
                    throw new IndexOutOfBoundsException();
                int newlen = len - (toIndex - fromIndex);
                int numMoved = len - toIndex;
                if (numMoved == 0)
                    setArray(Arrays.copyOf(elements, newlen));
                else {
                    Object[] newElements = new Object[newlen];   // 开新数组
                    System.arraycopy(elements, 0, newElements, 0, fromIndex);
                    System.arraycopy(elements, toIndex, newElements,
                                     fromIndex, numMoved);
                    setArray(newElements);
                }
            } finally {
                lock.unlock();
            }
        }
    
        // 当e不存在时,添加
        public boolean addIfAbsent(E e) {
            Object[] snapshot = getArray();
            return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
                addIfAbsent(e, snapshot);
        }
        private boolean addIfAbsent(E e, Object[] snapshot) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] current = getArray();
                int len = current.length;
                if (snapshot != current) {
                    // Optimize for lost race to another addXXX operation
                    int common = Math.min(snapshot.length, len);
                    for (int i = 0; i < common; i++)
                        if (current[i] != snapshot[i] && eq(e, current[i]))
                            return false;
                    if (indexOf(e, current, common, len) >= 0)
                            return false;
                }
                Object[] newElements = Arrays.copyOf(current, len + 1);
                newElements[len] = e;
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }
    
        public boolean containsAll(Collection<?> c) {
            Object[] elements = getArray();
            int len = elements.length;
            for (Object e : c) {
                if (indexOf(e, elements, 0, len) < 0)
                    return false;
            }
            return true;
        }
    
        public boolean removeAll(Collection<?> c) {
            if (c == null) throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (len != 0) {
                    // temp array holds those elements we know we want to keep
                    int newlen = 0;
                    Object[] temp = new Object[len];
                    for (int i = 0; i < len; ++i) {
                        Object element = elements[i];
                        if (!c.contains(element))
                            temp[newlen++] = element;
                    }
                    if (newlen != len) {
                        setArray(Arrays.copyOf(temp, newlen));
                        return true;
                    }
                }
                return false;
            } finally {
                lock.unlock();
            }
        }
    
        // 保留list- c的差集
        public boolean retainAll(Collection<?> c) {
            if (c == null) throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (len != 0) {
                    // temp array holds those elements we know we want to keep
                    int newlen = 0;
                    Object[] temp = new Object[len];
                    for (int i = 0; i < len; ++i) {
                        Object element = elements[i];
                        if (c.contains(element))
                            temp[newlen++] = element;
                    }
                    if (newlen != len) {
                        setArray(Arrays.copyOf(temp, newlen));
                        return true;
                    }
                }
                return false;
            } finally {
                lock.unlock();
            }
        }
    
        /**
         * Appends all of the elements in the specified collection that
         * are not already contained in this list, to the end of
         * this list, in the order that they are returned by the
         * specified collection's iterator.
         *
         * @param c collection containing elements to be added to this list
         * @return the number of elements added
         * @throws NullPointerException if the specified collection is null
         * @see #addIfAbsent(Object)
         */
        // 将集合c中存在的元素 而 list中没有的元素添加到list中
        public int addAllAbsent(Collection<? extends E> c) {
            Object[] cs = c.toArray();
            if (cs.length == 0)
                return 0;
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                int added = 0;
                for (int i = 0; i < cs.length; ++i) {  // e 不在elements(要加入) 且 也 cs里(不要重复的) 
                    Object e = cs[i];
                    if (indexOf(e, elements, 0, len) < 0 &&
                        indexOf(e, cs, 0, added) < 0)  
                        cs[added++] = e;
                }
                if (added > 0) {
                    Object[] newElements = Arrays.copyOf(elements, len + added);
                    System.arraycopy(cs, 0, newElements, len, added);
                    setArray(newElements);
                }
                return added;
            } finally {
                lock.unlock();
            }
        }
        public void clear() {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                setArray(new Object[0]);
            } finally {
                lock.unlock();
            }
        }
    
        
        // 
        public boolean addAll(Collection<? extends E> c) {
            Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
                ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();  // 集合c先数组化
            if (cs.length == 0) 
                return false;
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (len == 0 && cs.getClass() == Object[].class)
                    setArray(cs); 
                else {
                    Object[] newElements = Arrays.copyOf(elements, len + cs.length); // 先将元素组拷贝至新数组,多开cs.length个空间
                    System.arraycopy(cs, 0, newElements, len, cs.length);
                    setArray(newElements);
                }
                return true;
            } finally {
                lock.unlock(); //解锁
            }
        }
    
        public boolean addAll(int index, Collection<? extends E> c) {
            Object[] cs = c.toArray();
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (index > len || index < 0)
                    throw new IndexOutOfBoundsException("Index: "+index+
                                                        ", Size: "+len);
                if (cs.length == 0)
                    return false;
                int numMoved = len - index;
                Object[] newElements;
                if (numMoved == 0)
                    newElements = Arrays.copyOf(elements, len + cs.length);
                else {
                    newElements = new Object[len + cs.length];
                    System.arraycopy(elements, 0, newElements, 0, index);
                    System.arraycopy(elements, index,
                                     newElements, index + cs.length,
                                     numMoved);
                }
                System.arraycopy(cs, 0, newElements, index, cs.length);
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }
        // 迭代list,注意accept没有返回值哦
        public void forEach(Consumer<? super E> action) {
            if (action == null) throw new NullPointerException();
            Object[] elements = getArray();
            int len = elements.length;
            for (int i = 0; i < len; ++i) {
                @SuppressWarnings("unchecked") E e = (E) elements[i];
                action.accept(e);
            }
        }
        // 满足filter规则都都移除
        public boolean removeIf(Predicate<? super E> filter) {
            if (filter == null) throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (len != 0) {
                    int newlen = 0;
                    Object[] temp = new Object[len];
                    for (int i = 0; i < len; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) elements[i];
                        if (!filter.test(e))
                            temp[newlen++] = e;
                    }
                    if (newlen != len) {
                        setArray(Arrays.copyOf(temp, newlen));
                        return true;
                    }
                }
                return false;
            } finally {
                lock.unlock();
            }
        }
        // 对list中的所有元素进行 operator.apply(e)操作
        public void replaceAll(UnaryOperator<E> operator) {
            if (operator == null) throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len);
                for (int i = 0; i < len; ++i) {
                    @SuppressWarnings("unchecked") E e = (E) elements[i];
                    newElements[i] = operator.apply(e);
                }
                setArray(newElements);
            } finally {
                lock.unlock();
            }
        }
        // list的元素更具规则c排序
        public void sort(Comparator<? super E> c) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                Object[] newElements = Arrays.copyOf(elements, elements.length);
                @SuppressWarnings("unchecked") E[] es = (E[])newElements;
                Arrays.sort(es, c);
                setArray(newElements);
            } finally {
                lock.unlock();
            }
        }
        private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
    
            s.defaultWriteObject();
    
            Object[] elements = getArray();
            // Write out array length
            s.writeInt(elements.length);
    
            // Write out all elements in the proper order.
            for (Object element : elements)
                s.writeObject(element);
        }
    
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
    
            s.defaultReadObject();
    
            // bind to new lock
            resetLock();
    
            // Read in array length and allocate array
            int len = s.readInt();
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, len);
            Object[] elements = new Object[len];
    
            // Read in all elements in the proper order.
            for (int i = 0; i < len; i++)
                elements[i] = s.readObject();
            setArray(elements);
        }
    
        public String toString() {
            return Arrays.toString(getArray());
        }
    
       
        // 比较对象o和list是否相等:类型 长度 每个位置元素都相等 就为true
        public boolean equals(Object o) {
            if (o == this) // 同一引用,必然相等
                return true;
            if (!(o instanceof List)) // 都不是一个类型(也没有继承 实现 的关系)必然不相等
                return false;
    
            List<?> list = (List<?>)(o);   // list 执行列表对象o
            Iterator<?> it = list.iterator();
            Object[] elements = getArray();
            int len = elements.length;
            for (int i = 0; i < len; ++i)  // 长度相等 ,每个元素相等,就相等
                if (!it.hasNext() || !eq(elements[i], it.next()))  
                    return false;
            if (it.hasNext())
                return false;
            return true;
        }
    
        //返回list的hashCode
        public int hashCode() {
            int hashCode = 1;
            Object[] elements = getArray();
            int len = elements.length;
            for (int i = 0; i < len; ++i) {
                Object obj = elements[i];
                hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
            }
            return hashCode;
        }
    
        //根据list的一个快照,返回列表快照的一个单向迭代器,该迭代器不支持remove
        public Iterator<E> iterator() {
            return new COWIterator<E>(getArray(), 0);
        }
    
        // //根据list的一个快照,返回列表快照的一个双向迭代器,该迭代器不支持remove set add
        public ListIterator<E> listIterator() {
            return new COWIterator<E>(getArray(), 0);
        }
        public ListIterator<E> listIterator(int index) {
            Object[] elements = getArray();
            int len = elements.length;
            if (index < 0 || index > len)
                throw new IndexOutOfBoundsException("Index: "+index);
    
            return new COWIterator<E>(elements, index);
        }
    
        /**
         * Returns a {@link Spliterator} over the elements in this list.
         *
         * <p>The {@code Spliterator} reports {@link Spliterator#IMMUTABLE},
         * {@link Spliterator#ORDERED}, {@link Spliterator#SIZED}, and
         * {@link Spliterator#SUBSIZED}.
         *
         * <p>The spliterator provides a snapshot of the state of the list
         * when the spliterator was constructed. No synchronization is needed while
         * operating on the spliterator.
         *
         * @return a {@code Spliterator} over the elements in this list
         * @since 1.8
         */
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator
                (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
        }
    
        static final class COWIterator<E> implements ListIterator<E> {
            /** Snapshot of the array */
            private final Object[] snapshot;
            /** Index of element to be returned by subsequent call to next.  */
            private int cursor;
    
            private COWIterator(Object[] elements, int initialCursor) {
                cursor = initialCursor;
                snapshot = elements; //快照形成,snapshot时final的,
            }
    
            public boolean hasNext() {
                return cursor < snapshot.length;
            }
    
            public boolean hasPrevious() {
                return cursor > 0;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                if (! hasNext())
                    throw new NoSuchElementException();
                return (E) snapshot[cursor++];
            }
    
            @SuppressWarnings("unchecked")
            public E previous() {
                if (! hasPrevious())
                    throw new NoSuchElementException();
                return (E) snapshot[--cursor];
            }
    
            public int nextIndex() {
                return cursor;
            }
    
            public int previousIndex() {
                return cursor-1;
            }
    
        
            public void remove() {
                throw new UnsupportedOperationException();
            }
    
       
            public void set(E e) {
                throw new UnsupportedOperationException();
            }
    
        
            public void add(E e) {
                throw new UnsupportedOperationException();
            }
    
            @Override
            public void forEachRemaining(Consumer<? super E> action) {
                Objects.requireNonNull(action);
                Object[] elements = snapshot;
                final int size = elements.length;
                for (int i = cursor; i < size; i++) {
                    @SuppressWarnings("unchecked") E e = (E) elements[i];
                    action.accept(e);
                }
                cursor = size;
            }
        }
    
      
        //返回list的一个子视图([fromIndex,toIndex))
        public List<E> subList(int fromIndex, int toIndex) {
            final ReentrantLock lock = this.lock;
            lock.lock(); //加锁
            try {
                Object[] elements = getArray();
                int len = elements.length;
                if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
                    throw new IndexOutOfBoundsException();
                return new COWSubList<E>(this, fromIndex, toIndex);
            } finally {
                lock.unlock();
            }
        }
        
        private static class COWSubList<E>
            extends AbstractList<E>
            implements RandomAccess
        {
            private final CopyOnWriteArrayList<E> l;
            private final int offset;
            private int size;
            private Object[] expectedArray;
    
            // only call this holding l's lock
            COWSubList(CopyOnWriteArrayList<E> list,
                       int fromIndex, int toIndex) {
                l = list;
                expectedArray = l.getArray();  
                offset = fromIndex;
                size = toIndex - fromIndex;
            }
    
            // only call this holding l's lock
            private void checkForComodification() {
                if (l.getArray() != expectedArray)
                    throw new ConcurrentModificationException();
            }
    
            // only call this holding l's lock
            private void rangeCheck(int index) {
                if (index < 0 || index >= size)
                    throw new IndexOutOfBoundsException("Index: "+index+
                                                        ",Size: "+size);
            }
    
            public E set(int index, E element) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    rangeCheck(index);
                    checkForComodification();
                    E x = l.set(index+offset, element);
                    expectedArray = l.getArray();
                    return x;
                } finally {
                    lock.unlock();
                }
            }
    
            public E get(int index) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    rangeCheck(index);
                    checkForComodification();
                    return l.get(index+offset);
                } finally {
                    lock.unlock();
                }
            }
    
            public int size() {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    return size;
                } finally {
                    lock.unlock();
                }
            }
    
            public void add(int index, E element) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    if (index < 0 || index > size)
                        throw new IndexOutOfBoundsException();
                    l.add(index+offset, element);
                    expectedArray = l.getArray();
                    size++;
                } finally {
                    lock.unlock();
                }
            }
    
            public void clear() {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    l.removeRange(offset, offset+size);
                    expectedArray = l.getArray();
                    size = 0;
                } finally {
                    lock.unlock();
                }
            }
    
            public E remove(int index) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    rangeCheck(index);
                    checkForComodification();
                    E result = l.remove(index+offset);
                    expectedArray = l.getArray();
                    size--;
                    return result;
                } finally {
                    lock.unlock();
                }
            }
    
            public boolean remove(Object o) {
                int index = indexOf(o);
                if (index == -1)
                    return false;
                remove(index);
                return true;
            }
    
            public Iterator<E> iterator() {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    return new COWSubListIterator<E>(l, 0, offset, size);
                } finally {
                    lock.unlock();
                }
            }
    
            public ListIterator<E> listIterator(int index) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    if (index < 0 || index > size)
                        throw new IndexOutOfBoundsException("Index: "+index+
                                                            ", Size: "+size);
                    return new COWSubListIterator<E>(l, index, offset, size);
                } finally {
                    lock.unlock();
                }
            }
    
            public List<E> subList(int fromIndex, int toIndex) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    checkForComodification();
                    if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
                        throw new IndexOutOfBoundsException();
                    return new COWSubList<E>(l, fromIndex + offset,
                                             toIndex + offset);
                } finally {
                    lock.unlock();
                }
            }
    
            public void forEach(Consumer<? super E> action) {
                if (action == null) throw new NullPointerException();
                int lo = offset;
                int hi = offset + size;
                Object[] a = expectedArray;
                if (l.getArray() != a)
                    throw new ConcurrentModificationException();
                if (lo < 0 || hi > a.length)
                    throw new IndexOutOfBoundsException();
                for (int i = lo; i < hi; ++i) {
                    @SuppressWarnings("unchecked") E e = (E) a[i];
                    action.accept(e);
                }
            }
    
            public void replaceAll(UnaryOperator<E> operator) {
                if (operator == null) throw new NullPointerException();
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    int lo = offset;
                    int hi = offset + size;
                    Object[] elements = expectedArray;
                    if (l.getArray() != elements)
                        throw new ConcurrentModificationException();
                    int len = elements.length;
                    if (lo < 0 || hi > len)
                        throw new IndexOutOfBoundsException();
                    Object[] newElements = Arrays.copyOf(elements, len);
                    for (int i = lo; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) elements[i];
                        newElements[i] = operator.apply(e);
                    }
                    l.setArray(expectedArray = newElements);
                } finally {
                    lock.unlock();
                }
            }
    
            public void sort(Comparator<? super E> c) {
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    int lo = offset;
                    int hi = offset + size;
                    Object[] elements = expectedArray;
                    if (l.getArray() != elements)
                        throw new ConcurrentModificationException();
                    int len = elements.length;
                    if (lo < 0 || hi > len)
                        throw new IndexOutOfBoundsException();
                    Object[] newElements = Arrays.copyOf(elements, len);
                    @SuppressWarnings("unchecked") E[] es = (E[])newElements;
                    Arrays.sort(es, lo, hi, c);
                    l.setArray(expectedArray = newElements);
                } finally {
                    lock.unlock();
                }
            }
    
            public boolean removeAll(Collection<?> c) {
                if (c == null) throw new NullPointerException();
                boolean removed = false;
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    int n = size;
                    if (n > 0) {
                        int lo = offset;
                        int hi = offset + n;
                        Object[] elements = expectedArray;
                        if (l.getArray() != elements)
                            throw new ConcurrentModificationException();
                        int len = elements.length;
                        if (lo < 0 || hi > len)
                            throw new IndexOutOfBoundsException();
                        int newSize = 0;
                        Object[] temp = new Object[n];
                        for (int i = lo; i < hi; ++i) {
                            Object element = elements[i];
                            if (!c.contains(element))
                                temp[newSize++] = element;
                        }
                        if (newSize != n) {
                            Object[] newElements = new Object[len - n + newSize];
                            System.arraycopy(elements, 0, newElements, 0, lo);
                            System.arraycopy(temp, 0, newElements, lo, newSize);
                            System.arraycopy(elements, hi, newElements,
                                             lo + newSize, len - hi);
                            size = newSize;
                            removed = true;
                            l.setArray(expectedArray = newElements);
                        }
                    }
                } finally {
                    lock.unlock();
                }
                return removed;
            }
    
            public boolean retainAll(Collection<?> c) {
                if (c == null) throw new NullPointerException();
                boolean removed = false;
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    int n = size;
                    if (n > 0) {
                        int lo = offset;
                        int hi = offset + n;
                        Object[] elements = expectedArray;
                        if (l.getArray() != elements)
                            throw new ConcurrentModificationException();
                        int len = elements.length;
                        if (lo < 0 || hi > len)
                            throw new IndexOutOfBoundsException();
                        int newSize = 0;
                        Object[] temp = new Object[n];
                        for (int i = lo; i < hi; ++i) {
                            Object element = elements[i];
                            if (c.contains(element))
                                temp[newSize++] = element;
                        }
                        if (newSize != n) {
                            Object[] newElements = new Object[len - n + newSize];
                            System.arraycopy(elements, 0, newElements, 0, lo);
                            System.arraycopy(temp, 0, newElements, lo, newSize);
                            System.arraycopy(elements, hi, newElements,
                                             lo + newSize, len - hi);
                            size = newSize;
                            removed = true;
                            l.setArray(expectedArray = newElements);
                        }
                    }
                } finally {
                    lock.unlock();
                }
                return removed;
            }
    
            public boolean removeIf(Predicate<? super E> filter) {
                if (filter == null) throw new NullPointerException();
                boolean removed = false;
                final ReentrantLock lock = l.lock;
                lock.lock();
                try {
                    int n = size;
                    if (n > 0) {
                        int lo = offset;
                        int hi = offset + n;
                        Object[] elements = expectedArray;
                        if (l.getArray() != elements)
                            throw new ConcurrentModificationException();
                        int len = elements.length;
                        if (lo < 0 || hi > len)
                            throw new IndexOutOfBoundsException();
                        int newSize = 0;
                        Object[] temp = new Object[n];
                        for (int i = lo; i < hi; ++i) {
                            @SuppressWarnings("unchecked") E e = (E) elements[i];
                            if (!filter.test(e))
                                temp[newSize++] = e;
                        }
                        if (newSize != n) {
                            Object[] newElements = new Object[len - n + newSize];
                            System.arraycopy(elements, 0, newElements, 0, lo);
                            System.arraycopy(temp, 0, newElements, lo, newSize);
                            System.arraycopy(elements, hi, newElements,
                                             lo + newSize, len - hi);
                            size = newSize;
                            removed = true;
                            l.setArray(expectedArray = newElements);
                        }
                    }
                } finally {
                    lock.unlock();
                }
                return removed;
            }
    
            public Spliterator<E> spliterator() {
                int lo = offset;
                int hi = offset + size;
                Object[] a = expectedArray;
                if (l.getArray() != a)
                    throw new ConcurrentModificationException();
                if (lo < 0 || hi > a.length)
                    throw new IndexOutOfBoundsException();
                return Spliterators.spliterator
                    (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
            }
    
        }
    
        private static class COWSubListIterator<E> implements ListIterator<E> {
            private final ListIterator<E> it;
            private final int offset;
            private final int size;
    
            COWSubListIterator(List<E> l, int index, int offset, int size) {
                this.offset = offset;
                this.size = size;
                it = l.listIterator(index+offset);
            }
    
            public boolean hasNext() {
                return nextIndex() < size;
            }
    
            public E next() {
                if (hasNext())
                    return it.next();
                else
                    throw new NoSuchElementException();
            }
    
            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }
    
            public E previous() {
                if (hasPrevious())
                    return it.previous();
                else
                    throw new NoSuchElementException();
            }
    
            public int nextIndex() {
                return it.nextIndex() - offset;
            }
    
            public int previousIndex() {
                return it.previousIndex() - offset;
            }
    
            public void remove() {
                throw new UnsupportedOperationException();
            }
    
            public void set(E e) {
                throw new UnsupportedOperationException();
            }
    
            public void add(E e) {
                throw new UnsupportedOperationException();
            }
    
            @Override
            public void forEachRemaining(Consumer<? super E> action) {
                Objects.requireNonNull(action);
                int s = size;
                ListIterator<E> i = it;
                while (nextIndex() < s) {
                    action.accept(i.next());
                }
            }
        }
    
        // Support for resetting lock while deserializing
        private void resetLock() {
            UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
        }
        private static final sun.misc.Unsafe UNSAFE;
        private static final long lockOffset;
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> k = CopyOnWriteArrayList.class;
                lockOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("lock"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
    

    CopyOnWriteArrayList 示例

    
    
    
    

    面试session

    • 谈谈你对CopyOnWriteArrayList的理解?

    • 既然ArrayList不是线程安全的,那有何解决方案呢?
      使用Vector或者CopyOnWriteArrayList代替

    • 为什么选用CopyOnWriteArrayList不用Vector解决线程安全?
      由于没有绝对的线程安全,Vector对所有的方法都加了Sychronized修饰,效率十分低下,也不是绝对的线程安全,没必要;
      CopyOnWriteArrayList 采用 在修改列表结构时复制原列表的一个快照,对快照进行修改,对列表的读操作都不加锁,提高了效率。

    • 什么情况下,CopyOnWriteArrayList也是线程不安全的,如何做到线程安全?

  • 相关阅读:
    C语言 sprintf 函数 C语言零基础入门教程
    C语言 printf 函数 C语言零基础入门教程
    C语言 文件读写 fgets 函数 C语言零基础入门教程
    C语言 文件读写 fputs 函数 C语言零基础入门教程
    C语言 fprintf 函数 C语言零基础入门教程
    C语言 文件读写 fgetc 函数 C语言零基础入门教程
    C语言 文件读写 fputc 函数 C语言零基础入门教程
    C语言 strlen 函数 C语言零基础入门教程
    Brad Abrams关于Naming Conventions的演讲中涉及到的生词集解
    适配器模式
  • 原文地址:https://www.cnblogs.com/ahpucd/p/13491207.html
Copyright © 2011-2022 走看看