CopyOnWriteArrayList浅析

写在最前:CopyOnWriteArrayList适合使用在读操作远远大于写操作的场景里,比如缓存

除了加锁之外,还有一种技术可以防止并发修改异常,那就是读写分离技术

常识:

1、JAVA中“=”操作只是将引用和某个对象关联,假如同时有一个线程将引用指向另外一个对象,一个线程获取这个引用指向的对象,那么他们之间不会发生ConcurrentModificationException,他们是在虚拟机层面阻塞的,而且速度非常快,几乎不需要CPU时间。

2、JAVA中两个不同的引用指向同一个对象,当第一个引用指向另外一个对象时,第二个引用还将保持原来的对象。

分析:

在CopyOnWriteArrayList中,处理写操作(包括add、remove、set等)是通过Arrays.copyof()来生成新的数据对象,之后在新的数据对象进行读写,之后让旧的引用指向到新的数据对象,从而保证每次写都在新的数据对象上,维护数据的一致性(因为要保证写的一致性,这里要对各种写操作要加一把锁,JDK1.6在这里用了重入锁)

处理读操作的时候就是在引用的当前对象上进行读(包括get,iterator等),不存在加锁和阻塞,针对iterator使用了一个叫 COWIterator的阉割版迭代器,因为不支持写操作,当获取CopyOnWriteArrayList的迭代器时,是将迭代器里的数据引用指向当前 引用指向的数据对象,无论未来发生什么写操作,都不会再更改迭代器里的数据对象引用,所以迭代器也很安全(这里应用了常识2)。

CopyOnWriteArrayList中写操作需要大面积复制数组,所以性能肯定很差,但是读操作因为操作的对象和写操作不是同一个对象,读之 间也不需要加锁,读和写之间的同步处理只是在写完后通过一个简单的“=”将引用指向新的数组对象上来,这个几乎不需要时间,这样读操作就很快很安全,适合在多线程里使用,绝对不会发生并发修改异常。

引申:

在数据量较大时,性能亏损较大,每次进行写操作都会copy一份,而Array则不会,在要求性能的基础上,可以使用 volatile + arrayList 实现要求,使用了volatile后解决了并发修改问题,但会引入新的问题,那就是数组下标越界问题,所以此时不应使用通常的遍历方式for,而应该使用的是iterator进行遍历。

你可能感兴趣的:(CopyOnWriteArrayList浅析)