述
了解了并发安全的 HashMap
之后,再来看看并发安全的 ArrayList
,就是 CopyOnWriteArrayList
, 早期的版本中有 Vector
和 SynchronizedList
但是这两个锁的粒度太大,所以并发效率并不高, Copy-On-Write
并发容器还包括 CopyOnWriteArraySet
用来替代同步 Set
适用场景
CopyOnWriteArrayList
适用于读操作尽可能快,写操作可以慢一点的地方,或者读取比写入多的地方
读写规则
CopyOnWriteArrayList
读取完全不需要加锁,写入也不会阻塞读取操作,只有写入和写入之间需要同步等待
设计思想
CopyOnWrite
通俗的来说,就是往容器中添加一个元素的时候,不是直接往当前容器添加,而是先将当前的容器复制一份作为一个新的容器,然后在新的容器中添加,添加完成之后,再将原容器的引用指向新的容器,所以 CopyOnWrite
容器进行并发的读的时候,不需要加锁,因为当前容器不会添加任何元素,但是这样做将不能保证数据的实时性
用一个案例来看一下,代码如下
1 | public class ListTest { |
这段代码的运行结果如下1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
1
2
3
4
5
6
可以看到 iterator1
这个迭代器并没有6这元素
实现原理
看一下这个类的源码
这个类里面维护的就是一个数组
然后看看 add()
和 get()
方法
首先上锁,保证只有一个线程修改,先复制,改完之后把新的再放到上面的数组中,数组引用是 volatile
修饰的,因此将旧的数组引用指向新的数组,根据 volatile
的 happens-before
规则,写线程对数组引用的修改对读线程是可见的
get()
方法就很简单了,直接返回
缺点
- 不能保证数据一致性
- 内存占用,写操作的时候,内存中会有两个对象
总结
了解 CopyOnWriteArrayList
的原理,以及可能会带来的一些问题