ConcurrentModificationException on ArrayList - java

I'm getting an java.util.ConcurrentModificationException.
The related code is:
for (Iterator<Audit> it = this.pendingAudits.iterator(); it.hasNext();) {
// Do something
it.remove();
}
When it.remove() is called it throws me this exception.
This code is inside an #Serviceannotated class:
#Service
public class AuditService {
public AuditService(
this.pendingAudits = new ArrayList<Audit>();
}
public void flush(Audit... audits) {
this.pendingAudits.addAll(Arrays.asList(audits));
try {
for (Iterator<Audit> it = this.pendingAudits.iterator(); it.hasNext();) {
// Do something
it.remove();
}
}
}
}
The problem appears when two requests reach the code.
How could I avoid this concurrent access exception?

First things first, this is not a Spring-related problem. It's just a problem with a concurrent modification of one not-so-concurrent-friendly ArrayList class.
The simplest solution possible would be to synchronize access to the method that modifies it.
public synchronized void flush(Audit... audits) { }
Keep in mind that it will enforce the sequential execution of the flush method which imposes a huge performance penalty.
Sidenote, it's not enough to synchronize the collection itself by using Collections.synchronizedList - iterator instances returned by synchronized wrappers require manual synchronization.

Isn't it obvious? You are sharing data without proper synchronization.
#Service annotated class generally is a singleton scope class and hence the same instance will be shared among all calling threads.
This results into all threads accessing the flush method on the same instance.
And guess what?
Your flush method is trying to modify an ArrayList which is a member variable. This makes it unsafe in a multithreaded scenario.
It's a good time to revisit the documentation of ArrayList which tells a lot more things about it's iterator.
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. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:
List list = Collections.synchronizedList(new ArrayList(...));
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
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.

I think you probably put Audit into the list pendingAudits somewhere and you want to flush them all when you call the flush(Audit...) method, you can use ConcurrentLinkedQueue instead of ArrayList.
public AuditService(
this.pendingAudits = new ConcurrentLinkedQueue<Audit>();
}
public void flush(Audit... audits) {
this.pendingAudits.addAll(Arrays.asList(audits));
try {
Audit audit;
while ((audit = this.pendingAudits.poll) != null) {
// Do something
}
}
}

Related

synchronized collection getter

IIUC, a Collection that is only ever accessed by a synchronized method should be thread-safe - is that right?
e.g.,
class Foo {
private List<String> mList = new LinkedList<>();
public synchronized List<String> getList() {
return mList;
}
}
Assuming this getter is used exclusively to access the list - all operations are via getList() - it feels like it should be thread safe to me - but I'm very happy to be told I'm wrong.
TYIA
This would most likely not suffice as it simply returns a reference of the List; multiple threads would still be able to modify it concurrently, resulting in race conditions. If you're looking for a fully synchronized List, then I suggest using an ArrayList wrapped with Collections#synchronizedList.
Better you go for CopyOnWriteArrayList if you have much more reads than writes, Because its Synchronized and also the Iterator of CopyOnWriteArrayList is Fail-Safe and doesn't throw ConcurrentModificationException.
You can also make the existing list synchronized using Collections.synchronizedList(list) but the Iterator will be Fail-Fast.

JAVA java.util.ConcurrentModificationException

I am trying to create simple JAVA program. But since last day, I am having this issue, I cannot fix.
public void receiveUpdate(ArrayList<Connection> connections) {
for(Connection senderConnection : connections) {
for(Connection receiverConnection : this.connections) {
if(senderConnection.getDestination() == receiverConnection.getDestination()) {
if(senderConnection.getDistance() + 1 < receiverConnection.getDistance()) {
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.remove(receiverConnection);
this.connections.add(senderConnection);
}
}
}
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.add(senderConnection);
}
}
In this method I always get error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at router.Router.receiveUpdate(Router.java:56)
at router.Router.sendUpdate(Router.java:49)
at loader.Loader.notifyNetworkChanges(Loader.java:61)
at loader.Loader.main(Loader.java:102)
I have noticed, that exception doesn't appear if I comment block:
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.add(senderConnection);
Can anyone tell me, where is the problem?
ConcurrentModificationException This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
The problem is here
this.connections.remove(receiverConnection);
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Check this out
To solve your problem you need to use Iterator and remove() method like this
Iterator<String> connectionsIterator = connections.iterator();
while (connectionsIterator.hasNext()) {
if (senderConnection.getDistance() + 1 < receiverConnection.getDistance()){
connectionsIterator.remove();
// add the connection to another list other than this.connections.add(senderConnection);
// then when you finish add them back the this.connections
// so you avoid modifying this.connections
}
}
You are actually modifying the collections, while iterating.
this.connections.remove(receiverConnection);
this.connections.add(senderConnection);
Use an Iterator and call remove():
Iterator<String> iter = connections.iterator();
while (iter.hasNext()) {
if (someCondition)
iter.remove();
}
Use Iterator remove method instead of ArrayList
If you are modifying (eg deleting from) the same list you are looping then you are bound to get the ConcurrentModificationException
You can either use an iterator as #ankur-singhal mentioned or make a deep copy of the list and remove from that copy. Then you can assign the reference of the original list to point to the new one that has the modifications.
Another "greedy" approach (but without using iterators) would be to keep all items to be removed in another new list and after ending your for loop then call removeAll(listOfConnectionsToBeRemoved), for example:
before your for loops
ArrayList<Connection> connectionsToBeRemoved = new ArrayList<Connection>();
inside your for loops
connectionsToBeRemoved.add(receiverConnection)
after ending your for loops
this.connections.removeAll(connectionsToBeRemoved)
*you may do the same for connections to be added. Keep them in a new list and then add them all to your connection list.
You are looping through this.connections and inside you are trying to remove from this.connections this will java.util.ConcurrentModificationException. Change your code to use iterator.

Thread-safety simple

If I have a list of Components in a multithreading environnment and if I do any operation on this list except add (I use the keyword synchronized on the list in this case) and get (the method called by a component is thread-safe), is that thread-safe?
public class Test {
private final ArrayList<Component> myContainer = new ArrayList<Component>();
public void add(Component){
synchronized(myContainer){
myContainer.add(Component)
}
}
public void useComponents()
{
for(Component c : myContainer)
c.use(); // method thread-safe
}
// no other operations on myContainer
}
In the current form, it is not thread-safe: The useComponents method could be executed by one thread. At the same time, another thread could call add, and thus modify the collection while it is being iterated over. (This modification could happen between two calls to c.use(), so the fact that the use() method is thread safe would not help you here).
Strictly speaking, this is not even restricted to multithreading: If the c.use() internally called test.add(someOtherComponent) (even if it was done in the same thread!) this would throw a ConcurrentModificiationException, because again, the collection is modified while being iterated over.
Thread safety (without safety agains concurrent modifications) could be achieved by simply wrapping the iteration into a synchronized block:
public void useComponents()
{
synchronized (myContainer)
{
for(Component c : myContainer)
c.use(); // method thread-safe
}
}
However, this would still leave the possibility of a ConcurrentModificationException. Most likely the c.use() call will not (and should not) modify the collection that the component is contained in (otherwise, one could question the design in general).
If you wanted to allow the c.use() call to modify the collection, you could replace the collection with a CopyOnWriteArrayList:
private final List<Component> myContainer =
new CopyOnWriteArrayList<Component>();
and then you could even remove the synchroniziation completely. But you should be aware of the implications: The contents of the list will be copied during each modification (hence the name...). This is usually used in cases where you have a small collection that is frequently iterated over, but which is rarely modified. (Listeners in all forms are a classic example here).
It looks ok, except that I am not sure about iterator behavior in useComponents() if you'll simultaneously add elements to the list.
Did you consider using CopyOnWriteArrayList instead?

Java Enumeration vs Iterator

Enumeration doesn't throw ConcurrentModificationException , why?
See below code .
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration<String> en=v.elements();
while(en.hasMoreElements())
{
String value=(String) en.nextElement();
System.out.println(value);
v.remove(value);
}
}
It only prints :
Amit
Pathak
Aron
Why is this such behavior . Can we say that Enumerator is thread safe.
Edit: When working with Iterator it throws ConcurrentModificationException in single thread application.
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Iterator<String> it=v.iterator();
while(it.hasNext())
{
String value=(String) it.next();
System.out.println(value);
v.remove(value);
}
}
Please check.
Note that ConcurrentModificationException has nothing to do with concurrency in the sense of multithreading or thread safety. Some collections allow concurrent modifications, some don't. Normally you can find the answer in the docs. But concurrent doesn't mean concurrently by different threads. It means you can modify the collection while you iterate.
ConcurrentHashMap is a special case, as it is explicitly defined to be thread-safe AND editable while iterated (which I think is true for all thread-safe collections).
Anyway, as long as you're using a single thread to iterate and modify the collection, ConcurrentHashMap is the wrong solution to your problem. You are using the API wrongly. You should use Iterator.remove() to remove items. Alternatively, you can make a copy of the collection before you iterate and modify the original.
EDIT:
I don't know of any Enumeration that throws a ConcurrentModificationException. However, the behavior in case of a concurrent modification might not be what you expect it to be. As you see in you example, the enumeration skips every second element in the list. This is due to it's internal index being incremented regardless of removes. So this is what happens:
en.nextElement() - returns first element from Vector, increments index to 1
v.remove(value) - removes first element from Vector, shifts all elements left
en.nextElement() - returns second element from Vector, which now is "Pathak"
The fail-fast behavior of Iterator protects you from this kind of things, which is why it is generally preferable to Enumberation. Instead, you should do the following:
Iterator<String> it=v.iterator();
while(it.hasNext())
{
String value=(String) it.next();
System.out.println(value);
it.remove(); // not v.remove(value); !!
}
Alternatively:
for(String value : new Vector<String>(v)) // make a copy
{
String value=(String) it.next();
System.out.println(value);
v.remove(value);
}
The first one is certainly preferable, as you don't really need the copy as long as you use the API as it is intended.
Enumeration doesn't throw ConcurrentModificationException , why?
Because there is no path in the code being invoked which throws this exception. Edit: I am referring to the implementation provided by the Vector class, not about the Enumeration interface in general.
Why is this such behavior . Can we say that Enumerator is thread safe.
It is thread-safe in a sense that the code executed is properly synchronized. However, I don't think the result your loop yields is what you would except.
The reason for your output is that the Enumeration object maintains a counter, which is incremented after every invokation of nextElement(). This counter is not aware of your invokation of remove().
the fail-fast behaviour which throws the ConcurrentModificationException is only implemented for the Iterator as you can read in
http://docs.oracle.com/javase/6/docs/api/java/util/Vector.html
Concurrent modification here has nothing to do with threads.
Concurrency here simply means that you are modifying the collection while you are iterating over it. (In your example this happens in the same thread.)
Iterators and enumerations of collections can throw ConcurrentModificationException in this case, but don't have to. The ones that do exhibit fail-fast behaviour. Apparently, the enumeration of Vector isn't fail-fast.
Thread-safety obviously involves multiple threads somehow. Vector is thread-safe only in the sense that its operations (like add, get, etc.) are synchronized. This is to avoid non-deterministic behaviour when one thread is adding an element while at the same time another thread is trying to remove one for example.
Now, when one thread is structurally modifying your collection while another thread is iterating over it, you have to deal with both thread-safety and concurrent modification issues. In this case, and probably in general, it is safest not to rely on ConcurrentModificationException being thrown. It is best to choose the appropriate collection implementation (a thread-safe one for example) and avoid/disallow concurrent modification yourself.
Some iterators allow adding/setting/removing elements through the iterator itself. This can be a good alternative if you really need concurrent modification.
Short answer: It's a bonus feature that was invented after enumeration was already there, so the fact that the enumerator does not throw it does not suggest anything particular.
Long answer:
From wikipedia:
Collection implementations in pre-JDK 1.2 [...] did not contain a
collections framework. The standard methods for grouping Java
objects were via the array, the Vector, and the Hashtable classes,
which unfortunately were not easy to extend, and did not implement a
standard member interface. To address the need for reusable
collection data structures [...] The
collections framework was designed and developed primarily by Joshua
Bloch, and was introduced in JDK 1.2.
When the Bloch team did that, they thought it was a good idea to put in a new mechanism that sends out an alarm (ConcurrentModificationException) when their collections were not synchronized properly in a multi-threaded program. There are two important things to note about this mechanism: 1) it's not guaranteed to catch concurrency bugs -- the exception is only thrown if you are lucky. 2) The exception is also thrown if you misuse the collection using a single thread (as in your example).
So, a collection not throwing an ConcurrentModificationException when accessed by multiple threads does not imply it's thread-safe either.
It depends on how you get the Enumeration. See the following example, it does throw ConcurrentModificationException:
import java.util.*;
public class ConcurrencyTest {
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration<String> en=Collections.enumeration(v);//v.elements();
while(en.hasMoreElements())
{
String value=(String) en.nextElement();
System.out.println(value);
v.remove(value);
}
System.out.println("************************************");
Iterator<String> iter = v.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
iter.remove();
System.out.println(v.size());
}
}
}
Enumeration is just an interface, it's actual behavior is implementation-dependent. The Enumeration from the Collections.enumeration() call wraps the iterator in someway, so it's indeed fail-fast, but the Enumeration obtained from calling the Vector.elements() is not.
The not-fail-fast Enumeration could introduce arbitrary, non-deterministic behavior at an undetermined time in the future. For example: if you write the main method as this, it will throw java.util.NoSuchElementException after the first iteration.
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
Enumeration<String> en = v.elements(); //Collections.enumeration(v);
while(en.hasMoreElements())
{
v.remove(0);
String value=(String) en.nextElement();
System.out.println(value);
}
}
remove the v.remove(value) and everything will work as expected
Edit: sorry, misread the question there
This has nothing to do with threadsafety though. You're not even multithreading so there is no reason Java would throw an exception for this.
If you want exceptions when you are changing the vector make it Unmodifiable

Avoiding ConcurrentModificationException on List by making a shallow copy

I have a class like the following:
class Test
{
private LinkedList<Person> persons = new LinkedList<Person>;
public synchronized void remove(Person person)
{
persons.remove(person);
}
public List<Person> getAllPersons()
{
// Clients may iterate over the copy returned and modify the structure.
return new ArrayList<Person>(persons);
}
}
persons may be modified concurrently: one is via remove() by one thread and two via the shallow copied instance returned by getAllPersons().
I have tested the above scenario in a multithreaded environment to see if I can avoid ConcurrentModificationException by returning a shallow copy when getAllPersons() is called. It seemed to work. I have never once encountered a ConcurrentModificationException.
Why, in this case, does making only a shallow copy of persons avoid a ConcurrentModificationException?
A ConcurrentModificationException is thrown when a collection changes in a manner which invalidates open iterators. This usually happens when a collection which is not thread safe is accessed by multiple threads (although this is not the only cause)
There is still a small error in your code - to safely access a member which is not itself thread safe, you should synchronize on the getAllPersons method.
Assuming that is fixed -- because you are returning a copy, the collection itself cannot be modified by other callers (each gets their own copy). That means that you can never get a ConcurrentModificationException.
Note that this does not protect you against thread safety issues with your Person class, only the collections themselves. If Person is immutable, you should be OK.
In this case, a better solution would be to directly use a CopyOnWriteArrayList which implements similar semantics, but only copies when you actually write to the list - not every time you read from it.
That's because you are returning a copy of the List rather than the list itself. remove() is the only method which is modifying the actual list, accessible by multiple threads. Threads calling the getAllPersons() method will anyways getting a new list, so if they modify this list, its not going to change the original list.
So as your collection is not getting modified concurrently by threads you are not getting ConcurrentModificationException.

Categories

Resources