对于一些集合类,比如ArrayList,LinkedList,HashMap等等,我们可能会用锁来处理对它们的并发读写操作,或者通过java本身提供的集合类来解决并发问题。
以List为例,对于列表结构,如果要控制并发读写操作,以前要么自己加锁处理,要么利用Vector集合类,但是这会导致一些问题,暂且不说synchronized本身的开销,还会导致锁的粒度非常大。
比如Vector中元素非常多,每次读写操作会将数组中所有的元素访问都锁住,一个线程访问Vector中下标为1的元素,另一个线程访问Vector下标为2的元素,而且都是读操作,这样也会互斥。
CopyOnWrite
读操作能够并发执行,写操作是拷贝一份数据出来修改,修改后的数组为最新版本,将它赋值给内部的数组或者链表的引用。这比读写锁中对于读操作的控制粒度更低,因为写操作发生时,读操作依然可以进行。
有CopyOnWriteArrayList和CopyOnWriteArraySet,利用拷贝空间换取锁粒度的降低,适合读多写少的场合。对于并发的写操作依然是排它的,不允许两个操作同时写,当写非常频繁的时候,首先数组不会太小,所以拷贝出来的空间也会越大,会产生大量的垃圾碎片,这样还不如直接使用锁。
ConcurrentHashMap
key和value都不允许为空。它降map默认分为16段,每一段叫做segment,segment之间不存在并发征用(并行度可以修改,使用重载构造方法即可)。这样首先不需要拷贝大量内存,其次写的互斥只存在于同一个segment上面。