文章目录
- Why we use it?
- What does CopyOnWirte means?
- Source code of ADD method
- CopyOnWriteArrayList’s disadvantage
Why we use it?
- Since the ArrayList is not thread-safely, it will cause ConcurrentModificationException when we modify the array in a concurrent situation, so we choose to use CopyOnWriteArrayList
What does CopyOnWirte means?
-
It means copy the array to create a same one when you want to modify it, and seperate the read and write
-
That is to copy the original array to write on a separate copy, so this does not affect the read on the original array; Once written, point the original array reference to the new array.
-
The entire ADD operation is done under the protection of the lock.This is to avoid making multiple copies when adding multiple threads concurrently, which will mess up the data and cause the final array data to be not what we expect.
-
If there are concurrent reads from a thread, there are several cases:
- If the write operation is not completed, then directly read the data of the original array;
- If the write is complete, but the reference does not point to the new array, then the original array data is also read;
- If the write is complete and the reference is already pointing to the new array, read the data directly from the new array.
Source code of ADD method
/*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/
public boolean add(E e) {
final ReentrantLock lock = this.lock; // create a lock, this guarantee safe when concurrent happenlock.lock();try {
Object[] elements = getArray();// get the original arrayint len = elements.length; // get the length of original arrayObject[] newElements = Arrays.copyOf(elements, len + 1); // capacity + 1newElements[len] = e; // add operation setArray(newElements); // update the arrayreturn true;} finally {
lock.unlock();}
}
CopyOnWriteArrayList’s disadvantage
- Since the write operation copies the array, it consumes memory and may cause young GC or full GC if the original array is too large
- Cannot be used for real-time reading, such as copying array and adding new elements, it takes time, so after calling a set operation, the data read may still be old. Although CopyOnWriteArrayList can achieve the final consistency, it still cannot meet the real-time requirements.
CopyOnWriteArrayList is suitable for the scenario of reading more than writing, but this type is used with caution.Because there is no way to guarantee how much data CopyOnWriteArrayList will put into it, in case the data get too much and the array has to be re-copied every time add/set, this is too expensive.In high-performance Internet applications, this operation can cause a failure in minutes.