在实际的编程的时候我们肯定会遇到并发编程的时候,那我们就要考虑并发编程的时候,可能出现的问题。所以我们就要用到Java的并发包的类,去完成我们的工作。
今天我们就来分析CopyOnWriteArrayList这个并发容器,他是怎么做到的并发编程的。
我们不跟原来一样,直接贴代码,然后给大家一行一行的讲代码的意思。
我们分析思路
1。为什么他能做到,多个线程访问的时候,数据不会出错。
2。他是怎么做的,是加锁了?还是???
3。用的什么思想。
我们接下来就从这些问题入手
首先我们先了解这个东西是什么。
CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
接下来我们带着问题去分析源码。
1。首先我们还是看看他的类的结构。
2。我们从上面的问题出发。为什么能做到读写分离,是加锁?我们直接看add()方法。
看到这里大家可能就有点明白怎么回事了,圈出来的地方,申明了一个可重入锁,加锁方法保证写入数据。防止多个线程写的时候,copy出来很多个副本。然后里面就是一个简答的数组的复制,添加元素买最后释放锁,大家注意的是,我们需要把释放锁写在finally里面,保证一定能释放,这个锁是需要我们自己手动释放的,自己不会释放。
3。我们都知道,这个容器是读写分离,我们考虑看看,读的时候需不需要加锁,保证读的一致。
我们可以看到在读的时候是没有加锁的,那是因为我们在写的时候,没有锁住旧的副本,只是复制了一个新的而已,旧的没有变化。所以我们在读的时候读到的数据不是我们实时写进去的数据。读到的是旧的数据。
4。看到这里我们分析的就已经擦不多了,但是大家考虑到一个问题没有,一个东西不可能是完美的,CopyOnWrite容器能保证数据的弱一致,那么她有什么缺点?
数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。,我们能有别的容器代替?答案肯定是有的,我们可以用ConcurrentHashMap来代替他,下篇博客我们分析ConcurrentHashMap。
我们在读的操作比较多,写的操作比较少的时候,我们可以使用这个容器。