typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作

2023-08-26 0 1,679 百度已收录

一、概述

CopyOnWriteArrayList是Java中的并发集合类。 它是一个线程安全的List,可以被多个线程同时访问,但它的实现方法与其他线程安全的集合类不同。 它采用Copy-On-Write(写入时Copy)技术来保证线程安全。

2、CopyOnWriteArrayList原理

Copy-On-Write的原理是,当线程想要改变CopyOnWriteArrayList中的某个元素时,并不直接改变原来的链表,而是将原来的字段复制一次,然后在复制的新链表上执行。 进行更改,以便其他线程仍然可以安全地读取原始字段。 更改完成后,它将用新字段替换原始字段。 这样做的好处是更改操作不会影响其他线程的读操作,因为读操作总是读取原始字段。

三、CopyOnWriteArrayList源码

在CopyOnWriteArrayList的源码中,内部使用了一个volatile修饰的链表来存储数据。 该字段的类型为Object[]typescript 数组 清空,该字段是CopyOnWriteArrayList中元素实际存储的地方。 进行写操作时,会先复制原来的字段,然后对新的链表进行操作,最后用新的字段替换原来的字段。 其实这样做会有一定的成本,而且可以保证线程安全,同时也可以减少锁的使用。

CopyOnWriteArrayList提供了一些基本操作,如add、remove、get、set等,需要注意的是,由于CopyOnWriteArrayList的实现方法,它的迭代器不是强一致的,即在迭代过程中,如果其他线程发生变化CopyOnWriteArrayList 中的元素,迭代器可能会错过这些更改,因为它仍在迭代原始字段。 如果需要强一致的迭代器,可以使用Collections.synchronizedList方法将CopyOnWriteArrayList包装成线程安全的List,这样就可以获得强一致的迭代器。

总的来说,CopyOnWriteArrayList是一个线程安全的List,它采用Copy-On-Write技术来保证线程安全。 即使这样做有一定的开销,也可以减少锁的使用,提高并发性能。 需要注意的是,由于CopyOnWriteArrayList的实现方法的原因,它的迭代器并不是强一致的。 如果需要强一致的迭代器,可以使用 Collections.synchronizedList 方法将 CopyOnWriteArrayList 包装成线程安全的 List。

下面我们详细看一下CopyOnWriteArrayList的源码实现。

1.类的成员变量

CopyOnWriteArrayList类的主要成员变量包括:

typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作

java复制代码    /**
     * The lock protecting all mutators
     */
    final transient ReentrantLock lock = new ReentrantLock();
    /**
     * The array, accessed only via getArray/setArray.
     */
    private transient volatile Object[] array;

其中lock是一个ReentrantLock对象typescript 数组 清空,用于保证多个线程对List进行更改时的同步; array是CopyOnWriteArrayList内部维护的一个字段,用于存储List中的元素。

2、施工方法

CopyOnWriteArrayList类提供了两种构造方法:

scss复制代码    /**
     * Creates a new, empty list.
     */
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }
    /**
     * Creates a new list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection of initially held elements
     * @throws NullPointerException if the specified collection is null
     */
    public CopyOnWriteArrayList(Collection 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);
    }

typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作

第一种构造方法用于创建一个空List,其内部维护的字段是一个空链表; 第二种构造方法用于创建一个包含指定集合中元素的List,其中集合中的元素是通过toArray获取的,并将其复制到内部维护的字段中。

3、对外提供方式

CopyOnWriteArrayList类提供了一系列方法,包括:

typescript复制代码    public int size() {...}
    public boolean isEmpty() {...}
    public boolean contains(Object o) {...}
    public Object[] toArray() {...}
    public  T[] toArray(T[] a) {...}
    public boolean add(E e) {...}
    public boolean remove(Object o) {...}
    public boolean containsAll(Collection c) {...}
    public boolean addAll(Collection c) {...}
    public boolean addAll(int index, Collection c) {...}
    public boolean removeAll(Collection....

4. 核心技能

typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作

CopyOnWriteArrayList的核心技能包括:

五、CopyOnWriteArrayList异同

通过上面的分析我们可以发现,CopyOnWriteArrayList的核心思想是通过改变时复制底层链表来实现线程安全。 这些实现方法各有优缺点,下面我们将分别介绍。

优势:

高效的读操作:由于读操作不需要加锁,因此可以避免读写冲突带来的等待时间,从而提高读操作的效率。 线程安全:线程安全是通过在改变时复制底层链表来实现的,从而避免改变操作时的读写冲突。

typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作

缺点:

显存占用:由于每次改变都需要复制底层链表,因此会占用较多的显存。 写操作效率低:由于每次写操作都需要复制底层链表,所以写操作效率低。

综上所述,CopyOnWriteArrayList在读多写少的场景下性能较好,但在写多读少的场景下性能较差。 为此,在使用CopyOnWriteArrayList时需要根据实际情况进行选择。

六、CopyOnWriteArrayList使用场景

最后,我们还需要注意CopyOnWriteArrayList的一些使用限制和注意事项:

仅适合大型列表:由于每次更改都需要复制底层链表,因此 CopyOnWriteArrayList 仅适合大型列表。 对于小列表,使用 CopyOnWriteArrayList 可能会导致内存使用率较低。 适用于读多写少的场景:由于每次写操作都需要复制底层链表,因此CopyOnWriteArrayList适合读多写少的场景。 不支持并发更改:CopyOnWriteArrayList不支持并发更改,因为每次更改都需要复制底层链表。 如果需要支持并发更改,请使用其他线程安全的 List 实现。 迭代器快照:由于每个写入操作还会复制底层链表,因此迭代器返回快照而不是列表的实时视图。 如果列表在迭代期间发生更改,则可能会引发 ConcurrentModificationException。

事实上,CopyOnWriteArrayList是一个非常有用的线程安全List实现,它通过在底层链表发生变化时进行复制来实现线程安全。 使用CopyOnWriteArrayList时,需要注意其使用限制和注意事项,从而充分发挥其优点,防止其缺点。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 typescript typescript 数组 清空-如何正确使用CopyOnWriteArrayList实现线程安全的List操作 https://www.wkzy.net/game/156334.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务