84

I am learning about the CopyOnWriteArrayList class.

  • What is the purpose of copying a new array?
  • Is it for other threads to read the array?

So if a system has high concurrency and most of the threads' actions are reading not writing, it is better to use CopyOnWriteArrayList.

Bartosz Bilicki
  • 12,599
  • 13
  • 71
  • 113
huashui
  • 1,758
  • 2
  • 16
  • 24

2 Answers2

103

As stated on this link:

CopyOnWriteArrayList is a concurrent Collection class introduced in Java 5 Concurrency API along with its popular cousin ConcurrentHashMap in Java.

CopyOnWriteArrayList implements List interface like ArrayList, Vector and LinkedList but its a thread-safe collection and it achieves its thread-safety in a slightly different way than Vector or other thread-safe collection class.

As name suggest CopyOnWriteArrayList creates copy of underlying ArrayList with every mutation operation e.g. add or set. Normally CopyOnWriteArrayList is very expensive because it involves costly Array copy with every write operation but its very efficient if you have a List where Iteration outnumber mutation e.g. you mostly need to iterate the ArrayList and don't modify it too often.

Iterator of CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException even if underlying CopyOnWriteArrayList is modified once Iteration begins because Iterator is operating on separate copy of ArrayList. Consequently all the updates made on CopyOnWriteArrayList is not available to Iterator.

To get the most updated version do a new read like list.iterator();

That being said, updating this collection alot will kill performance. If you tried to sort a CopyOnWriteArrayList you'll see the list throws an UnsupportedOperationException (the sort invokes set on the collection N times). You should only use this read when you are doing upwards of 90+% reads.

Ghosy
  • 40
  • 1
  • 7
Ankur Lathi
  • 7,636
  • 5
  • 37
  • 49
  • And if you need to add items very frequently to the list and sometimes need to remove all. Do you think the 'synchronized' way is the better approach? – John John Pichler Sep 14 '14 at 13:51
  • 2
    You can consider `java.util.concurrent` package over `Collections.synchronizedList`. – Ankur Lathi Sep 14 '14 at 14:06
  • I'm already using it. But it seems to work just when I combine with the old `synchronized` keyword. – John John Pichler Sep 14 '14 at 14:21
  • Just read here and now I got it. We need no use `synchronized` keyword when you iterate a `Set`, even when we use `Collections.synchronizedList`. – John John Pichler Sep 14 '14 at 14:24
  • ".. even if underlying CopyOnWriteArrayList is modified once Iteration begins because Iterator is operating on separate copy of ArrayList" Do you mean, because the modification actually is made on a separate copy? – Koray Tugay Jul 01 '17 at 09:27
  • @KorayTugay Yes, It iterates over a copy of original list. – Ankur Lathi Jul 02 '17 at 17:03
  • Can it throw `ConcurrentModificationException ` if I update the copy as I iterate over it (on the same thread)? – stdout Mar 11 '20 at 09:14
  • 1
    @stdout - no it won't throw ConcurrentModificationException . It is a fail safe collection which uses a seperate copy for iteration. – Ankur Lathi Mar 13 '20 at 02:42
  • One mistake here , "sort a CopyOnWriteArrayList you'll see the list throws an UnsupportedOperationException ", NO,NO, call sort method of CopyOnWriteArrayList will works good and also I have read the source code and executed a test. – Li-Tian Oct 23 '20 at 13:27
  • From java8, you can sort CopyOnWriteArrayList using cowlist.sort(null) with null comparator – Bhaskar13 Jan 14 '23 at 16:06
28

What is the purpose of coping a new array?

Copying the underlying array guarantees that any iteration of the data structure is safe as the iteration is occurring over an essentially immutable "snapshot" of the data.

Is it for other threads to read the array?

Sort of. More specifically, it is for every thread to be able to safely iterate the array without fear of a ConcurrentModificationException or other unknown/undefined behavior.

So if a system is high concurrency and most of the threads' actions are reading not writing, it is better to use CopyOnWriteArrayList. Am I right?

No. Only if most of the threads' actions are iterations over the list. If most of the activities are random access based reads, a ReadWriteLock might be better.

From the javadoc of CopyOnWriteArrayList

This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • could you explain why `ReadWriteLock` might be better? – Konstantin Milyutin May 04 '16 at 14:04
  • 8
    Because the `CopyOnWriteArrayList` is for safe traversals. The cost of using it is duplicating the underlying array of references for each modification and possibly retaining multiple copies for threads iterating over stale versions of the structure. A `ReadWriteLock` would allow multiple readers and still let the occasional writer perform the necessary modifications. – Tim Bender May 05 '16 at 06:19