Alex Bishop
Alex Bishop

Reputation: 483

Effects of concurrent access to an unsynchronised Java ArrayList

Imagine the following scenario:

I have a standard Java ArrayList<String>.

This ArrayList<String> is accessed by multiple threads with no explicit synchronisation, subject to the following constraints:

  1. Multiple reads may occur at the same time (possibly concurrent with the write described below). All reads call the iterator() method on the ArrayList<String> and exclusively use the returned Iterator<E> (iterators are not shared between threads). The only methods called on the Iterator<String> are hasNext() and next() (the remove() method is not called).
  2. One thread may write to the list (possibly concurrent with reads but not concurrent with other writes). Each write only calls the add(String) and remove(Object) methods on the ArrayList<E>.

I know the follow to be true:

  1. The read threads may see outdated data.
  2. The read threads may experience a ConcurrentModificationException.

Apart from the above two problems, can anything else go wrong?

I am looking for specific examples (of the form, if x and y are true, then z will occur, where z is bad). It has to be something that can actually happen in practice. Please provide citations where possible.

(I personally think that other failures are possible but I have been challenged to come up with specific examples of why the above scenario is not suitable for production code.)

Upvotes: 0

Views: 268

Answers (1)

antlersoft
antlersoft

Reputation: 14786

I would expect that your readers or your writer could get an ArrayIndexOutOfBounds exception or a null pointer exception, as well, since they can be seeing inconsistent state of the underlying array.

You really are at the mercy of the detailed implementation of the ArrayList class-- which can vary from environment to environment. It is possible that the JVM could implement the class with native code that could cause worse undefined behavior (JVM crash) when reading without synchronization.

I'll add this from the text of the ConcurrentModificationException reference page:

Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

In short, you can't depend on nothing bad happening besides stale data and ConcurrentModificationException.

Upvotes: 3

Related Questions