views:

449

answers:

7

We have multiple threads calling add(obj) on an ArrayList.

My theory is that when add is called concurrently by two threads, that only one of the two objects being added is really added to the ArrayList. Is this plausable?

If so, how do you get around this? Use a synchronized collection like Vector?

A: 

you can use List l = Collections.synchronizedList(new ArrayList()); if you want thread safe version of arrayList.

Shamik
A: 

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ArrayList.html

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.

Since there is no synchronization internally, what you theorize is not plausible.

So, things get out of sync, with unpleasant and unpredictable results.

WhirlWind
Right, saw that. I had thought that a `ConcurrentModificationException` would have been thrown which is not happening for us.. maybe we're running into another side affect of not using a thread safe collection..
Marcus
@Marcus that appears to only be the case if you modify the list while iterating over it. Also, there is no guarantee this exception will be thrown.
WhirlWind
A: 

java.util.concurrent has a thread-safe array list. The standard ArrayList is not thread-safe and the behavior when multiple threads update at the same time is undefined. There can also be odd behaviors with multiple readers when one or more threads is writing at the same time.

Tom Cabanski
+1  A: 

You could also get a null, an ArrayOutOfBoundsException, or something left up to the implementation. HashMaps have been observed to go into an infinite loop in production systems. You don't really need to know what might go wrong, just don't do it.

You could use Vector, but it tends to work out the interface is not rich enough. You will probably find that you want a different data structure in most cases.

Tom Hawtin - tackline
+5  A: 

There is no guaranteed behavior for what happens when add is called concurrently by two threads on ArrayList. However, it has been my experience that both objects have been added fine. Most of the thread safety issues related to lists deal with iteration while adding/removing. Despite this, I strongly recommend against using vanilla ArrayList with multiple threads and concurrent access.

Vector used to be the standard for concurrent lists, but now the standard is to use the Collections synchronized list.

Also I highly recommend Java Concurrency in Practice by Goetz et al if you're going to be spending any time working with threads in Java. The book covers this issue in much better detail.

derivation
"it has been my experience that both objects have been added fine" just want to point out that this is just sheer luck. Likely the window for a data corruption issue with ArrayList is extremely small, but it still exists
matt b
Right, and that's sort of my point. In the vast majority of cases there will be no problem; but we don't program to the majority of cases. Thus why I strongly recommended against using ArrayList.
derivation
+1  A: 

The behavior is probably undefined since ArrayList isn't threadsafe. If you modify the list while an Iterator is interating over it then you will get a ConcurrentModificationException. You can wrap the ArrayList with Collection.synchronizedList or use a thread-safe collection (there are many), or just put the add calls in a synchronized block.

BrennaSoft
+6  A: 

Any number of things could happen. You could get both objects added correctly. You could get only one of the objects added. You could get an ArrayIndexOutOfBounds exception because the size of the underlying array was not adjusted properly. Or other things may happen. Suffice it to say that you cannot rely on any behavior occurring.

As alternatives, you could use Vector, you could use Collections.synchronizedList, you could use CopyOnWriteArrayList, or you could use a separate lock. It all depends on what else you are doing and what kind of control you have over access to the collection.

Matthew T. Staebler