1,简介
CopyOnWriteArrayList是一个在多线程操作中线程安全的ArrayList的一个变种,她在所有对ArrayList对象的编辑操作(add,set等)都会复制一份副本( Object[] newElements = Arrays.copyOf(elements, len + 1);),因此无论是对ArrayList操作还是对其iterator操作都不会抛ConcurrentModificationException异常。
看CopyOnWriteArrayList源码,首先把ArrayList的源码看懂了,再看CopyOnWriteArrayList你会感觉到几乎和ArrayList实现原理一样,只是CopyOnWriteArrayList给其内的Write(add(E e),set(int index,E e)等)方法上了ReentrantLock锁,CopyOnWriteArrayList是一个线程安全,读操作时无锁的ArrayList。
2,原理
其实现原理还是数组的扩容:Arrays.copyOf(T[] original, int newLength)
3,总结:
CopyOnWriteArrayList通过编辑操作复制元数据副本的方式成功避免了多线程操作List线程不安全的问题,同时通过声明array[]为volitile类型保证线程每次读取的数据都是最新数据。
由于每次编辑操作都会复制一份副本,因此CopyOnWriteArrayList只适用于读多改少的场景,在其他场景中还是建议使用synchronize或者Collections.SynchronizedList来保证线程安全
线程安全,读操作时无锁的ArrayList
底层数据结构是一个Object[],初始容量为0,之后每增加一个元素,容量+1,数组复制一遍
增删改上锁、读不上锁
遍历过程由于遍历的只是全局数组的一个副本,即使全局数组发生了增删改变化,副本也不会变化,所以不会发生并发异常
读多写少且脏数据影响不大的并发情况下,选择CopyOnWriteArrayList
注:读多写少且脏数据影响不大的并发情况下,选择CopyOnWriteArrayList是因为CopyOnWriteArrayList维护一个ReentrantLock锁,主要用于保证同一时间只能有一个线程对array数据进行复制编辑操作(set,add等),避免多线程下对数据复制操作造成数据不一致现象。 同时array声明为volatile,保证线程读取数据时将内存的数据刷新至缓存,从而得到最新数据。写入数据时保证最新数据写入到内存。在CopyOnWriteArrayList所有操作中,获取数据和写入数据不是直接使用this.array=array,而是使用getArray()和setArray()操作,刷新一下缓存,保证获得的是最新数据及将最新数据写入内存。
CopyOnWriteArrayList是一个在多线程操作中线程安全的ArrayList的一个变种,她在所有对ArrayList对象的编辑操作(add,set等)都会复制一份副本( Object[] newElements = Arrays.copyOf(elements, len + 1);),因此无论是对ArrayList操作还是对其iterator操作都不会抛ConcurrentModificationException异常。
看CopyOnWriteArrayList源码,首先把ArrayList的源码看懂了,再看CopyOnWriteArrayList你会感觉到几乎和ArrayList实现原理一样,只是CopyOnWriteArrayList给其内的Write(add(E e),set(int index,E e)等)方法上了ReentrantLock锁,CopyOnWriteArrayList是一个线程安全,读操作时无锁的ArrayList。
2,原理
其实现原理还是数组的扩容:Arrays.copyOf(T[] original, int newLength)
3,总结:
CopyOnWriteArrayList通过编辑操作复制元数据副本的方式成功避免了多线程操作List线程不安全的问题,同时通过声明array[]为volitile类型保证线程每次读取的数据都是最新数据。
由于每次编辑操作都会复制一份副本,因此CopyOnWriteArrayList只适用于读多改少的场景,在其他场景中还是建议使用synchronize或者Collections.SynchronizedList来保证线程安全
线程安全,读操作时无锁的ArrayList
底层数据结构是一个Object[],初始容量为0,之后每增加一个元素,容量+1,数组复制一遍
增删改上锁、读不上锁
遍历过程由于遍历的只是全局数组的一个副本,即使全局数组发生了增删改变化,副本也不会变化,所以不会发生并发异常
读多写少且脏数据影响不大的并发情况下,选择CopyOnWriteArrayList
注:读多写少且脏数据影响不大的并发情况下,选择CopyOnWriteArrayList是因为CopyOnWriteArrayList维护一个ReentrantLock锁,主要用于保证同一时间只能有一个线程对array数据进行复制编辑操作(set,add等),避免多线程下对数据复制操作造成数据不一致现象。 同时array声明为volatile,保证线程读取数据时将内存的数据刷新至缓存,从而得到最新数据。写入数据时保证最新数据写入到内存。在CopyOnWriteArrayList所有操作中,获取数据和写入数据不是直接使用this.array=array,而是使用getArray()和setArray()操作,刷新一下缓存,保证获得的是最新数据及将最新数据写入内存。