您的位置:

CopyOnWriteArrayList线程安全吗

一、CopyOnWriteArrayList简介

CopyOnWriteArrayList是Java中并发集合类之一,实现了List接口,通过对内部数组进行copy-on-write的方式来保证线程安全性。简单来说,就是在修改时先对当前数组进行复制,然后进行修改,最后将复制后的新数组赋值给当前数组。这种方式在读多写少的情况下能够提供比较好的读写性能。

二、CopyOnWriteArrayList线程安全机制

CopyOnWriteArrayList通过对内部数组进行复制,以分离写操作和读操作的锁,从而保证线程安全。在进行写操作时,首先对当前数组进行复制,然后针对新的数组进行修改,最后将新的数组赋值给当前数组,完成写操作。在读取操作时,直接读取当前数组即可,因为操作的是一个不可变的数组,读取时不存在线程安全问题。

三、CopyOnWriteArrayList的优缺点

3.1 优点

1、线程安全:由于在进行读写操作时,读操作对原始数组只进行读取,不会修改,所以读操作不需要进行锁定操作,可以同时进行,从而提高并发性。

2、适用于读多写少的场景:由于每次进行写操作时都需要进行数组复制,所以在写操作比较频繁的情况下CopyOnWriteArrayList的性能会比较低。但是在读操作比较频繁的情况下,由于读操作不需要使用锁,因此能够提供很好的性能。

3.2 缺点

1、内存占用:由于每次进行写操作都需要进行数组复制,因此需要占用较大的内存空间。

2、修改操作的延迟:在进行写操作时,需要先对原始数组进行复制,然后在复制的数组上进行修改,最后再将修改后的数组赋值给原始数组,这个过程需要一定的时间,因此可能会出现修改操作的延迟。

四、CopyOnWriteArrayList线程安全示例

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {

    private static final int THREAD_POOL_SIZE = 2;

    public static void main(String[] args) throws InterruptedException {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        //添加元素
        list.add("Java");
        list.add("Python");
        list.add("C++");

        //创建两个线程向list中添加元素
        Runnable task = () -> {
            for (int i = 0; i < 100; i++) {
                list.add(Thread.currentThread().getName() + ":" + i);
            }
        };
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        executorService.submit(task);
        executorService.submit(task);

        //等待所有线程执行完成
        executorService.shutdown();
        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

        //输出list中所有元素
        for (String str : list) {
            System.out.println(str);
        }
    }
}

上述示例代码通过创建两个线程向CopyOnWriteArrayList添加元素,由于CopyOnWriteArrayList的线程安全机制,在并发执行时不会出现线程安全问题,每个线程可以安全地执行写操作。