Collections. SynchronizedList ()、CopyOnWriteArrayList 与 Vector 有什么区别?

Collections. SynchronizedList ()CopyOnWriteArrayListVector 都是线程安全的集合。

  1. Vector

    Vector 的同步做法是给所有公有方法都加上 “Synchronized”[^1] 关键字。

    1
    2
    3
    4
    5
    6
    7
    8
    //Vector
    public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
    }

  1. Collections. SynchronizedList ()

    当使用 Collections. SynchronizedList () 方法创建线程安全的 List 时,会根据 List 类型(时候实现了 Post not found: RandomAccessas 接口)返回 SynchronizedRandomAccessListSynchronizedList,前者继承于后者,两者在使用上并无差别。

    1
    2
    3
    4
    5
    6
    7
    8
    9
     // Collections.synchronizedList
    // 根据传入的List类型返回相应的内部类
    public static <T> List<T> synchronizedList(List<T> list) {
    return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list));
    }

    static <T> List<T> synchronizedList(List<T> list, Object mutex) {
    return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list, mutex) : new SynchronizedList<>(list, mutex));
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     //SynchronizedRandomAccessList 继承自 SynchronizedList
    static class SynchronizedRandomAccessList<E> extends SynchronizedList<E> implements RandomAccess {

    SynchronizedRandomAccessList(List<E> list) {
    super(list);
    }

    SynchronizedRandomAccessList(List<E> list, Object mutex) {
    super(list, mutex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
    synchronized (mutex) {
    return new SynchronizedRandomAccessList<>(list.subList(fromIndex, toIndex), mutex);
    }
    }
    private static final long serialVersionUID = 1530674583602358482L;

    /**
    * Allows instances to be deserialized in pre-1.4 JREs (which do * not have SynchronizedRandomAccessList). SynchronizedList has * a readResolve method that inverts this transformation upon * deserialization. */
    private Object writeReplace() {
    return new SynchronizedList<>(list);
    }
    }

    SynchronizedList 继承自 SynchronizedCollection,一些共有的方法,SynchronizedCollection 都做了实现,基本做法都是使用 Post not found: Synchronized 关键字修饰代码块。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //SynchronizedList继承自SynchronizedCollection
    static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E>{}
    //SynchronizedList类方法
    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);}
    }

    SynchronizedList 中获取 “ListIterator”[^11] 的方法不是同步的,在使用的时候需要自己添加同步代码块。

    1
    2
    3
    4
    5
    6
    7
    //需要额外注意的是遍历遍历方法不是同步的
    public ListIterator<E> listIterator() {
    return list.listIterator(); // Must be manually synched by user
    }
    public ListIterator<E> listIterator(int index) {
    return list.listIterator(index); // Must be manually synched by user
    }

    虽然 SynchronizedList 看起来是将同步范围缩小了,仅对 mutex 对象资源锁定,但是 mutex 默认是 this,这造就了相比 VectorSynchronizedList 的效率并不会变高。

  2. CopyOnWriteArrayList

  在实际使用中,如果需要保证 List 的线程安全,推荐使用 Post not found: CopyOnWriteArrayList

  总的来讲,单线程场景下,推荐使用 ArrayList 保证更高的效率。
多线程场景下,如果是查询多余修改的场景,推荐使用 CopyOnWriteArrayList,如果是修改多余查询的场景,推荐使用 VectorSynchronizedList

评论