Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CopyOnWriteArrayList throwing CurrentModificationException

I'm occasionally getting a ConcurrentModificationException when I iterate over a list. A Google search informs me that it's probably because I'm altering that list in another thread while iterating over it and that to make this problem go away I should use java.util.concurrent.CopyOnWriteArrayList....

... except I already am.

Apparently, I'm doing something really stupid somewhere.

Does anybody have any insight into how one might induce CopyOnWriteArrayList to toss a ConcurrentModificationException? If it matters, I'm using Java 5.

Edit: Since the mutators I'm using may matter, I'm modifying this list in two ways:

  • Adding elements to the front. (list.add(0, newElement);)
  • Using subList to let older items fall off the back. (list = list.subList(0, MAX_LIST_SIZE);)

Do those raise red flags? If so, why? My understanding was that because these operations make a copy of the thing first, any existing iterators would be pointing at the unmodified original and would thus not care. Do I have a hole in my knowledge?

Edit 2: The precise code that's causing the problem is still a bit murky, but I can at least post the exception I'm seeing:


java.util.ConcurrentModificationException
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
    at....

... where it points to a for-each loop instantiation in my code.

That COWSubList does seem to imply that my call to subList is the root of my problem; I'd still like to understand why.

Edit 3: *facepalm*

CopyOnWriteArrayList.subList() returns a List, not a CopyOnWriteArrayList. The list it returns is under no implied obligation to provide any of COWAL's protections. Which makes using subList() like this to remove elements a Very Bad Idea.

Don't know for certain if this is my culprit, but it's damned suspicious and needs to be corrected regardless.

like image 687
BlairHippo Avatar asked Oct 06 '09 19:10

BlairHippo


People also ask

How do I fix concurrent modification exception?

How do you fix Java's ConcurrentModificationException? There are two basic approaches: Do not make any changes to a collection while an Iterator loops through it. If you can't stop the underlying collection from being modified during iteration, create a clone of the target data structure and iterate through the clone.

Which method of the iterator throws concurrent modification exception?

If we invoke a sequence of methods on an object that violates its contract, then the object throws ConcurrentModificationException. For example: if while iterating over the collection, we directly try to modify that collection, then the given fail-fast iterator will throw this ConcurrentModificationException.

What causes concurrent modification exception?

What Causes ConcurrentModificationException. The ConcurrentModificationException generally occurs when working with Java Collections. The Collection classes in Java are very fail-fast and if they are attempted to be modified while a thread is iterating over it, a ConcurrentModificationException is thrown.

Can Concurrenthashmap throws ConcurrentModificationException?

They do not throw ConcurrentModificationException.


1 Answers

CopyOnWriteArrayList.subLists throw ConcurrentModificationExceptions if the containing list changes out from underneath it:

public class ListTest {

  private static List<int[]> intList;

  public static void main (String[] args) {
    CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
    cowal.add(1);
    cowal.add(2);
    cowal.add(3);

    List<Integer> sub = cowal.subList(1, 2);
    cowal.add(4);
    sub.get(0); //throws ConcurrentModificationException
  }
}
like image 54
Sbodd Avatar answered Nov 10 '22 00:11

Sbodd