Reputation: 11651
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 ?
Upvotes: 0
Views: 972
Reputation: 11651
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());
}
}
Upvotes: 0
Reputation: 1580
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
.
Upvotes: 0
Reputation: 1240
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.
Upvotes: 2