美文网首页Java js css html
[Java]重学Java-CopyOnWriteArrayLis

[Java]重学Java-CopyOnWriteArrayLis

作者: AbstractCulture | 来源:发表于2023-01-19 23:50 被阅读0次

CopyOnWriteArrayList

在没有JUC前,线程安全的List我们可以用Collections.synchronizedList().现在多了一种选择,就是今天所说的CopyOnWriteArrayList.
CopyOnWriteArrayList采用的是写时复制策略,即真正需要更新列表的时候,会从原有的数组上进行一个复制,然后在这个复制出来的列表上做更新操作.

类图

UML

从类图我们可以知道,CopyOnWriteArrayList有2个元素,lock是用来保证只有一个线程可以对当前对象进行修改的锁,array则存放了列表中的数据.

为什么CopyOnWriteArrayList能保证线程安全?

构造函数

  • java.util.concurrent.CopyOnWriteArrayList#CopyOnWriteArrayList(java.util.Collection<? extends E>)
    /**
     * Creates a 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<? extends E> 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);
    }

将传入的集合转换成数组,然后赋值或者复制给array变量.这里从注释上我们可以知道,CopyOnWriteArrayList是保证有序的.

add

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return {@code true} (as specified by {@link Collection#add})
 */
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();
    }
}

1.添加元素的时候,先获取独占锁,保证互斥性.
2.成功获取锁的线程,对代码块进行上锁,然后获取原来列表的元素数组,复制一份到元素大小为length+1的数组中,然后在尾部添加需要被add的元素.
3.释放锁
这里我们可以总结一下:copyOnWriteArrayList对于这种增删的操作,它是能保证线程安全的,其次,每次做增删,都需要对原数组进行复制操作赋值到新的数组上,这正是copy-on-wrtie的思想体现.

CopyOnWriteArrayList的弱一致性

在读操作的时候,如果数组正在进行复制行为,那么此时读到的是旧数组的数据,JDK只能保证数据的最终一致性,无法保证实时一致性,所以CopyOnWriteArrayList比较适合读多写少的场景。

具体可以看JDK的注释介绍:

Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a CopyOnWriteArrayList happen-before actions subsequent to the access or removal of that element from the CopyOnWriteArrayList in another thread.

内存一致性影响:与其他并发集合一样,在将对象放入CopyOnWriteArrayList之前,线程中的操作发生在另一个线程中访问或从CopyOnWriteArray中删除该元素之后的操作之前。

相关文章

  • [Java]重学Java-CopyOnWriteArrayLis

    CopyOnWriteArrayList 在没有JUC前,线程安全的List我们可以用Collections.sy...

  • 重学Java

    为什么要学 首先是Java应用广泛,Java无疑是应用最广泛的一门语言,不仅可以开发桌面型应用,也可以开发Web应...

  • java重学之路

    工作了几年 把java的很多基本知识已经忘了 今天开始java的重新学习 整理些基本资料 以备翻阅 2017年06...

  • 重学java系列

    背景 毕业已经一年,面向业务编程也已经一年,期间学习了一本新的jvm语言。但回过头来看,自己刚入门java的时候,...

  • [Java]重学Java-继承

    复用 随着码代码的时间增长,程序员会越发需要"复用"这个能力,比如最简单的对String类进行判空: 我们需要每次...

  • [Java]重学Java-集合

    容器 很多时候,我们写程序需要进行批量的操作,比如说,新增一批学生列表.那么就需要有容器来装下这10个对象。Jav...

  • [Java]重学Java-接口

    接口是什么 首先接口不是类,它本身是无法被实例化的,只有实现类可以被实例化。它更像是一种功能的描述,程序输入什么值...

  • [Java]重学Java-多态

    从一个例子理解多态 对于一个不同特征的对象,使用接口可以隐藏子类的行为,对外暴露同一个接口,从而实现编程的解耦. ...

  • [Java]重学Java-List

    UML 列表底层的数据结构 Java中的列表都是可以动态伸缩的。跟数组不一样,数组超过了一定的长度,会直接报越界异...

  • [Java]重学Java-Map

    HashMap 关于HashMap的源码解析,笔者已经写过,这里不在重复介绍. HashSet-集合 如果你需要判...

网友评论

    本文标题:[Java]重学Java-CopyOnWriteArrayLis

    本文链接:https://www.haomeiwen.com/subject/pgaqhdtx.html