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 Thread
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 whichThreadB
is attempting to access simultaneously, assuming that you don't care whether or notThreadB
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.
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.
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.