CopyOnWriteArrayLis简单使用

背景

Collections.synchronizedList()、Vector虽然线程安全,但是使用的synchronized锁实现,锁粒度较粗,且迭代时候不允许修改,否则会抛出异常,鉴于这种情况,java.util.concurrent包下提供了CopyOnWriteArrayList、CopyOnWriteSet一类的并发集合,本文以CopyOnWriteArrayList为例,简单聊聊这个线程安全且效率高一些的并发容器。

CopyOnWriteArrayList特点

  • 线程安全,支持迭代中修改集合;
  • 支持并发读及并发读写,但是并发写需要阻塞同步,从这点看CopyOnWriteArrayList比较适合读多写少情况;

copyOnWriteArrayList=[A, B, C, D]
当前值=A
copyOnWriteArrayList=[A, B, C]
当前值=B
copyOnWriteArrayList=[A, B, C]
当前值=C
copyOnWriteArrayList=[A, B, C, F]
当前值=D

可以发现,CopyOnWriteArrayList不同于ArrayList,在迭代中支持修改,"F"被添加进了数组且"D"被安全移除,但是最后一次打印iterator.next()方法输出的还是被移除的"D"而不是"F",原因在于iterator对象是的获取是在"F"被添加之前,要想顺利获取“F”元素,则在添加元素之后再次获取迭代对象即可。

CopyOnWriteArrayList源码分析

CopyOnWriteArrayList的关键在于会将数组拷贝一份,真正操作的是数组的副本,这一点和java内存模型(工作内存只操作变量的朱内存副本拷贝)、ThreadLocal类(线程本地存储)有很大的类比性,也是CopyOnWriteArrayList为什么是线程安全的核心

CopyOnWriteArrayList的核心方法就是add(),简单分析下做了哪些事情:

  • 使用ReentrantLock上锁;
  • 得到当前数组对象,并且复制一个新数组;
  • 将待添加元素放入新数组中;
  • 将CopyOnWriteArrayList中的数组array引用指向新数组;
  • 释放锁;
    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();
        }
    }

CopyOnWriteArrayList不足之处

  • CopyOnWrite思想,导致数据会存在两份,占用空间变多;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值