I read that a ConcurrentModificationException
can be thrown whenever a thread performs a structural modification upon a certain list while another thread is iterating over its elements. To detect such modification, instances of the class List
store the number of times they were modified in a field called modCount
, whose value is checked at each iteration of the list to check whether the latter was modified. If my understanding was correct, access to modCount
needs to be synchronized, because if the list in question was to be modified after checking the value of modCount
in the last iteration and before the end of the loop, the iterator would fail to detect that the list was modified during its last iteration.
Everything you've said is correct, and perfectly normal. modCount
is not atomic, and the iterator could fail to detect that the list was modified, and that's fine. Revisit the ArrayList documentation:
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
Because ArrayList
does not try to guarantee that it will always detect a concurrent modification, it can avoid the overhead of an atomic variable for a case that should never happen in correct code. The use of the unsynchronized modCount
detects the most common cases, and will sometimes (depending on exact thread ordering and the like) detect cases that are truly concurrent. Remember, though, that ConcurrentModificationException
almost never happens because concurrency is actually going on, but because someone calls a modification method during an iteration loop.