eye_mew
eye_mew

Reputation: 9133

ArrayList concurrent access

I am aware that ArrayList is not thread safe, but I'm unsure about the exact implications of this.

In the case of ThreadA and ThreadB both using an ArrayList, which of these situations will cause issues and necessitate synchronization?

  1. Both threads simultaneously reading the same index
  2. ThreadA replacing an element which ThreadB is attempting to access simultaneously, assuming that you don't care whether or not ThreadB gets the old or the new element.

Upvotes: 4

Views: 5879

Answers (3)

Gray
Gray

Reputation: 116858

Both threads simultaneously reading the same index

It is okay for multiple threads to be reading from common ArrayList if the list was constructed by the thread that forked the ThreadA and ThreadB and the list is fully constructed and loaded before the threads were forked.

The reason for this is that there is a happens-before guarantee with a thread and the memory of the thread that forked it. If, for example, ThreadC builds the ArrayList but after ThreadA and ThreadB are forked, then there is no guarantee that A and B will fully see the ArrayList -- if at all.

If this is not the case then you will need to synchronize the list. See below.

ThreadA changing an element which ThreadB is attempting to access simultaneously, assuming that you don't care whether or not ThreadB gets the old or the new element.

Once you talk about modifications to the list in a concurrent setting, then you must synchronize on that list otherwise there is no guarantee that the modifications will be published and there are chances that the list could be partially published which could cause data exceptions. As @Marko puts it, its internal state may be inconsistent.

You can either use a CopyOnWriteArrayList which is designed for few updates and many reads, use Collections.synchronizedList(...) to make your list be protected, you can access the list always in a synchronized block (for all writes and reads), or you can switch to using a concurrent collection such as ConcurrentSkipList or something.

ThreadA changing an element which ThreadB is attempting to access simultaneously

This is somewhat ambiguous. If you are talking about, for example, storing objects in the list and then changing the objects that happen to be stored in the list then you are not going to have a synchronization problem on the list but you will have a synchronization problem with the object. If the list's data is not changing then it will be fine. However, if you need to protect the object then either a list of AtomicReference<YourObject>, volatile fields in the object, or other synchronization is required to make sure the changes are published between the threads.

Upvotes: 3

Marko Topolnik
Marko Topolnik

Reputation: 200148

In your question I see an emphasis on simultaneous access.

The issues with concurrent access have very little to do with simultaneity. To put it more strongly, even if you ensure no simultaneous access happens, you are still a long way from a thread-safe program.

Answers to your specific points:

1) Both threads simultaneously reading the same index

As long as your threads only read and never write, you are safe regardless of simultaneity.

2) ThreadA changing an element which ThreadB is attempting to access simultaneously, assuming that you don't care whether or not ThreadB gets the old or the new element.

Whether or not writing happens at the same time as reading, you are in trouble. You are not just in danger of seeing stale values; you can see a completely broken List object (its internal state is inconsistent).

If any thread changes the list, you need synchronization.

For more information I strongly advise getting acquainted with the Java Memory Model, preferrably from the corresponding section in the Java Language Specification.

Upvotes: 2

lance-java
lance-java

Reputation: 27976

If you initialize the list prior to publishing it, there's no problem with having multiple threads reading from the list.

As soon as you are reading and writing to the list concurrently, you need to synchronize access to it.

Upvotes: 0

Related Questions