CopyOnWriteArrayLis简单使用

Java编程之路 同时被 2 个专栏收录
119 篇文章 14 订阅
107 篇文章 4 订阅

背景

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思想,导致数据会存在两份,占用空间变多;
  • 0
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页

打赏

饭一碗

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值