简体   繁体   中英

Understanding snapshots in CopyOnWriteArrayList

I have few issues in understanding this concept. Please correct me where I am wrong.

Basically, iteration makes a snapshot (copy) of original array, thus threads that modify collection won't affect our iteration because iteration uses a copy. So no ConcurrentException here, nice.

But then I also read that any modification is done by making a copy of original collection and using that copy to make changes. Then it sets it to original one.

Can someone tell me why is there need to make a copy when modifying, when iteration already uses its own copy. Why have 2 copes, one for read, one for write?

I think I said something incorrect, so please can you point what am I missing?

When CopyOnWriteArrayList creates an iterator, the "snapshot" is a reference to its current array - not a copy of the array.

The iterator can use a reference to the array because the array is never modified. CopyOnWriteArrayList does that the name says: it makes a new copy of the array when anything is changed. If some iterator using the old array at the same time, that's not a problem, the iterator will just keep using the old array and it will not see any of the modifications made to the list. This makes the iterator "weakly consistent."

The javadoc for CopyOnWriteArrayList says the following:

The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created . This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException .

You asked:

Basically, iteration makes a snapshot (copy) of original array, thus threads that modify collection won't affect our iteration because iteration uses a copy. So no ConcurrentException here, nice.

...

I think I said something incorrect, so please can you point what am I missing?

The javadoc does not say that the iterator copies the state of the list, or makes a snapshot . It says that it uses a reference to the state of the list at the point in time that the iterator.

The state copying happens when the list is mutated, as explained elsewhere in the javadoc.

This is obviously what you were missing.

Hints: 1) Always read the javadoc carefully. 2) If you want to confirm what the javadoc says, read the source code. But bear in mind that the source code may include implementation details that are not part of the API spec, and may change between different Java versions.


Followup question.

Why is there need to make modifications on copy, when iterator uses snapshot and it doesn't see any modifications until it is finished?

Because if CopyOnWriteArrayList didn't make a fresh copy each time the list is modified, then existing iterators would see the modifications ... in all ill-defined way.

The other alternatives are:

  1. Use a lock to block any modifications while the list is being iterated. This would be a concurrency bottleneck.
  2. Create the snapshot each time you start an iteration. This would also be a concurrency bottleneck because you need to block modifications while the snapshot is created.

Note that CopyOnWriteArrayList is designed for use-cases where the list is most read and seldom modified. For such use-cases, copying on modify is a good strategy. But if the list needs to be modified a lot, this is a bad strategy ... and the CopyOnWriteArrayList is the wrong choice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM