0

I get an ConcurrentModificationException error in following situation. The line where this occurs is marked with "<-------- ConcurrentModificationException"

  • I have a main thread which reads from a list as follow:

    List<ThemeCacheIndex> list = Collections.synchronizedList(themeCacheList);
    synchronized (list) {
        Iterator<ThemeCacheIndex> it = list.iterator();
        while (it.hasNext()) {
            ThemeCacheIndex themeCacheIndex = it.next();  <-------- ConcurrentModificationException
            doSomething();
        }
    }
    
  • I have a AsyncTask which deletes from this list:

     @Override
        protected String doInBackground(String... params) {
            someElementsToRemove = calculateWhichElementsToRemove();
            for(int i=0 ; i < someElementsToRemove.size() ; i++){
                themeCacheList.remove(someElementsToRemove.get(i));
            }
        }
    

I can imagine, that it comes to a concurrent situation, but I thought to prevent this with a synchronized list on the main thread.

It seems I did not understood the concept of multithreading and shared objects.

Can someone help me out of this problem ? How can I prevent this conflict ?

mcfly soft
  • 11,289
  • 26
  • 98
  • 202
  • 1
    The object you synchronize on must be the same. With `Collections.synchronizedList(themeCacheList)` you're creating a new object. – devgianlu Apr 10 '19 at 15:55
  • So when I created a new object, why can I get still a concurrent problem. I mean I created this as a new list. – mcfly soft Apr 10 '19 at 15:57
  • `synchronized` works only if you use it on the same object as the other block. Post the AsyncTask code so that I can show you what I mean. – devgianlu Apr 10 '19 at 15:59
  • 1
    If something else has access to the `themeCacheList` variable, then it can still be modified outside this list. – Andy Turner Apr 10 '19 at 15:59
  • 1
    Possible duplicate of [Is List.iterator() thread-safe?](https://stackoverflow.com/questions/5847939/is-list-iterator-thread-safe) – ghoul932 Apr 10 '19 at 16:02
  • I have added the code from my backgroundtask. Would be very happy if someone shows me howto solve this. A codehint would maybe open my eyes. – mcfly soft Apr 10 '19 at 17:17
  • 1
    FYI, `ConcurrentModificationException` is just one of many tragically-misnamed features in Java. It has nothing to do with "concurrency." It means that your program tried to use an iterator that was created for some container, but the container had been modified some time between when iterator was created and when the program tried to use it. Even a single-threaded program can do that. – Solomon Slow Apr 10 '19 at 17:24
  • Thank you for the explanation of the problem. But how can I solve this ? I coudn't find any solution for this. Can someone give me a hint or a link or anything else to proactive find a solution. – mcfly soft Apr 10 '19 at 17:30
  • @devgianlu. Thanks for helping. Would be happy if you can show me what you mean. – mcfly soft Apr 10 '19 at 17:54
  • Is maybe CopyOnWriteArrayList , what I need to use ? – mcfly soft Apr 10 '19 at 18:26
  • Possible duplicate: https://stackoverflow.com/a/55550252/5349869 – raviiii1 Apr 10 '19 at 18:59

3 Answers3

2

Quoting Collections Javadoc:

Returns a synchronized (thread-safe) list backed by the specified list. In order to guarantee serial access, it is critical that all access to the backing list is accomplished through the returned list.

If your AsyncTask modifies the themeCacheList, the synchronization as you did it won't help, as a backing list is modified.

igorepst
  • 1,230
  • 1
  • 12
  • 20
0

The AsyncTask code is fine. Do this for the "main" thread code:

synchronized (themeCacheList) {
    Iterator<ThemeCacheIndex> it = themeCacheList.iterator();
    while (it.hasNext()) {
        ThemeCacheIndex themeCacheIndex = it.next();
        doSomething();
    }
}

As you can see I've removed Collections.synchronizedList because it is redundant and I'm synchronizing directly on themeCacheList.

devgianlu
  • 1,547
  • 13
  • 25
0

Not sure I have a good solution, but I guess these 2 examples shows the problem and a possible solution. The "Possible duplicate" Answers do not show any solution, but just explaining what is the problem.

@Test
public void testFails(){

    List<String> arr = new ArrayList<String>();
    arr.add("I");
    arr.add("hate");
    arr.add("the");
    arr.add("ConcurrentModificationException !");

    Iterator i = arr.iterator();


    arr.remove(2);

    while(i.hasNext()){
        System.out.println(i.next());
    }
}

@Test
public void testWorks(){

    List<String> arr = new CopyOnWriteArrayList<>();
    arr.add("I");
    arr.add("hate");
    arr.add("the");
    arr.add("ConcurrentModificationException !");

    Iterator i = arr.iterator();


    arr.remove(2);

    while(i.hasNext()){
        System.out.println(i.next());
    }
}
mcfly soft
  • 11,289
  • 26
  • 98
  • 202