美文网首页
CopyOnWriteArrayList

CopyOnWriteArrayList

作者: _chubby | 来源:发表于2019-03-19 16:16 被阅读0次

    CopyOnWriteArrayList是一种线程安全的ArrayList实现

    它使用的是一种写时复制的方法,当有新元素添加到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组

    它定义了一个内部数组,并且只能通过getArray()、setArray()操作,保证操作的原子性

     /** The array, accessed only via getArray/setArray. */
        private transient volatile Object[] array;
    
        /**
         * Gets the array.  Non-private so as to also be accessible
         * from CopyOnWriteArraySet class.
         */
        final Object[] getArray() {
            return array;
        }
    
        /**
         * Sets the array.
         */
        final void setArray(Object[] a) {
            array = a;
        }
    

    定义了一把锁,对所有的写操作上锁,保证同一时刻只有一个线程进行写操作

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

    示例-添加

        /**
         * 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();
            }
        }
    

    示例-移除

     /**
         * Removes the first occurrence of the specified element from this list,
         * if it is present.  If this list does not contain the element, it is
         * unchanged.  More formally, removes the element with the lowest index
         * {@code i} such that
         * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
         * (if such an element exists).  Returns {@code true} if this list
         * contained the specified element (or equivalently, if this list
         * changed as a result of the call).
         *
         * @param o element to be removed from this list, if present
         * @return {@code true} if this list contained the specified element
         */
        public boolean remove(Object o) {
            Object[] snapshot = getArray();
            int index = indexOf(o, snapshot, 0, snapshot.length);
            return (index < 0) ? false : remove(o, snapshot, index);
        }
    
        /**
         * A version of remove(Object) using the strong hint that given
         * recent snapshot contains o at the given index.
         */
        private boolean remove(Object o, Object[] snapshot, int index) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] current = getArray();
                int len = current.length;
                if (snapshot != current) findIndex: {   //java8,增加了复杂性。
                    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();
            }
        }
    

    所有的读操作都是不需要加锁的

    示例-获取

         /**
         * {@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];
        }
    

    优缺点

    高性能的读取,适合读远大于写的场景

    写操作需要拷贝数组,容易导致gc、只能保证最终一致性,不能够保证实时读取

    相关文章

      网友评论

          本文标题:CopyOnWriteArrayList

          本文链接:https://www.haomeiwen.com/subject/xehnmqtx.html