CopyOnWriteArrayList 与 Collections.synchronizedList

疑问点:

前者有两个get(int index)重载方法,怎么判断什么时候用哪个?

源码对比:
CopyOnWriteArrayList 在写时会加锁,同时操作时会拷贝一个新的数组以存放新的字段

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

CopyOnWriteArrayList在读时不会加锁

    public E get(int index) {
        return get(getArray(), index);
    }


=======================
疑惑为啥会有两个重载方法

        public E get(int index) {
            final ReentrantLock lock = l.lock;
            lock.lock();
            try {
                rangeCheck(index);
                checkForComodification();
                return l.get(index+offset);
            } finally {
                lock.unlock();
            }
        }

Collections.synchronizedList

其实现线程安全的方式时建立 list 的包装类

    public static  List synchronizedList(List list) {
        return (list instanceof RandomAccess ?
                new SynchronizedRandomAccessList<>(list) :
                new SynchronizedList<>(list));
    }

通过对部分方法加锁的方式实现线程安全

        public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return list.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return list.hashCode();}
        }

        public E get(int index) {
            synchronized (mutex) {return list.get(index);}
        }
        public E set(int index, E element) {
            synchronized (mutex) {return list.set(index, element);}
        }
        public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        }
        public E remove(int index) {
            synchronized (mutex) {return list.remove(index);}
        }

        public int indexOf(Object o) {
            synchronized (mutex) {return list.indexOf(o);}
        }
        public int lastIndexOf(Object o) {
            synchronized (mutex) {return list.lastIndexOf(o);}
        }

        public boolean addAll(int index, Collection c) {
            synchronized (mutex) {return list.addAll(index, c);}
        }

值得注意的时其迭代器的方法没加锁

        public ListIterator listIterator() {
            return list.listIterator(); // Must be manually synched by user
        }

        public ListIterator listIterator(int index) {
            return list.listIterator(index); // Must be manually synched by user
        }

性能对比之下可知:

写操作:在线程数目增加时CopyOnWriteArrayList的写操作性能下降非常严重,而Collections.synchronizedList虽然有性能的降低,但下降并不明显。


读操作:在多线程进行读时,Collections.synchronizedList和CopyOnWriteArrayList均有性能的降低,但是Collections.synchronizedList的性能降低更加显著
 

你可能感兴趣的:(concurrent,java)