CopyOnWriteArrayList源码解读

概述
CopyOnWriteArrayList是jdk concurrent包中提供的一个非阻塞型的,线程安全的List实现。
CopyOnWriteArrayList在进行数据修改时,都不会对数据进行锁定,每次修改时,先拷贝整个数组,然后修改其中的一些元素,完成上述操作后,替换整个数组的指针。
对CopyOnWriteArrayList进行读取时,也不进行数据锁定,直接返回需要查询的数据,如果需要返回整个数组,那么会将整个数组拷贝一份,再返回,保证内部array在任何情况下都是只读的。

应用场景
正因为上述读写特性,如果需要频繁对CopyOnWriteArrayList进行修改,而很少读取的话,那么会严重降低系统性能。
因为没有锁的干预,所以CopyOnWriteArrayLIst在少量修改,频繁读取的场景下,有很好的并发性能。

数据结构
CopyOnWriteArrayList中,包含一个array数组对象,这个对象,只能由getArray()和setArray()两个方法访问,源码如下:

private volatile transient Object[] array; final Object[] getArray() { return array; } final void setArray(Object[] a) { array = a; }


并发安全保证
CopyOnWriteArrayList在并发情况下,可以提供高性能的并发读取,并且保证读取的内容一定是正确的,不受多线程并发问题影响的。在本文中,我们从构造函数的并发安全性、访问单个元素的并发安全性、访问整个数组的并发安全性和写操作的并发安全性,四个方面进行分析。

构造函数的并发安全性
CopyOnWriteArrayList提供了三个构造函数,分别为
  • CopyOnWriteArrayList():构造一个内容为空的对象
  • CopyOnWriteArrayList(Collection<? extends E> c):根据传入参数中的内容,构造一个新的对象
  • CopyOnWriteArrayList(E[] toCopyIn):根据传入数组中的内容,构造一个新的对象
上述三个方法的源码如下:

public CopyOnWriteArrayList() { setArray(new Object[0]); } /** * 根据传入参数c的长度,构造一个同样长度的Object[]对象,并且将c的内容,依次填入此Object[]对象中

* 注意:

* 1. 这里对于c中内容的复制,是浅拷贝而非深拷贝

* 2. 这里的构造函数,未显式判断c是否为null,实际上如果c为null,会抛出空指针异常 */ public CopyOnWriteArrayList(Collection<? extends E> c) { Object[] elements = c.toArray(); if (elements.getClass() != Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); setArray(elements); } /** * 根据传入参数的长度,构造出一个同样长度,内容一致的数组对象,封装在CopyOnWriteArrayList中

* 注意:

* 1. 这里对于数组内容的复制,是浅拷贝而非深拷贝

* 2. 这里的构造函数,未显式判断传入参数是否为null,实际上如果传入参数为null,会抛出空指针异常 */ public CopyOnWriteArrayList(E[] toCopyIn) { setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); }


访问单个元素的并发安全性
访问单个元素时,不会对原有数组造成任何影响,所以肯定是线程安全的。这里列举一两个方法的实现源码,其他的不再赘述:

public E get(int index) { return (E)(getArray()[index]); }

public int indexOf(Object o) { /* 

* 在取数组元素前,获取当前时刻array对象的引用至关重要 

* 在后续文章描述中可以知道,CopyOnArrayList在set操作时,会更新array对象的引用

* 这里如果不事先获得引用,那么后面实际的indexOf操作,会因为并发问题,得到意想不到的结果,还可能出现数组越界异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值