user123321
user123321

Reputation: 12794

Getting a ConcurrentModificationException but I'm not removing

What am I getting a ConcurrentModificationException with this code? I have a synchronized(listeners) lock.

private void notifyListeners(MediumRendition rendition) {
    if (rendition == null) return;
    synchronized (listeners) {
        for (RenditionEventListener l : listeners) {
            if (l.renditionType.equals(rendition.getType()) && l.mediumId == rendition.getMediumId()) {
                l.listener.onRendition(rendition);
            }
        }
    }
}

public void put(String renditionType, long mediumId, MediumRendition rendition) {
    HashMap<Long, MediumRendition> l = list.get(renditionType);
    if (l == null) {
        l = new HashMap<Long, MediumRendition>();
        list.put(renditionType, l);
    }
    l.put(mediumId, rendition);
    notifyListeners(rendition);
}

public void addRenditionListener(String renditionType, long mediumId, RenditionListener listener) {
    synchronized (listeners) {
        listeners.add(new RenditionEventListener(renditionType, mediumId, listener));
    }
}

01-30 16:47:55.147 6953 6974 E AndroidRuntime: FATAL EXCEPTION: Thread 1 01-30 16:47:55.147 6953 6974 E AndroidRuntime: java.util.ConcurrentModificationException 01-30 16:47:55.147 6953 6974 E AndroidRuntime: at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573) 01-30 16:47:55.147 6953 6974 E AndroidRuntime: at com..vos.RenditionList.notifyListeners(RenditionList.java:79) 01-30 16:47:55.147 6953 6974 E AndroidRuntime: at com.t.vos.RenditionList.put(RenditionList.java:41) 01-30 16:47:55.147 6953 6974 E AndroidRuntime: at com.*.controllers.OmwController$6.run(OmwController.java:212)

SOLVED: Apparently I was removing. See below.

Upvotes: 0

Views: 252

Answers (2)

Sushil Kadu
Sushil Kadu

Reputation: 314

Concurrency is kind of tricky. In the context of your application, though, you may not see that you are not modifying the list but it is getting modified somewhere when you call

l.listener.onRendition(rendition);

The possible solutions are as below.

  1. Use ConcurrentLinkedQueue instead of ArrayList. You don't need to write synchronize block if you use this collection. This is the simplest solution.
  2. If 1. doesn't work, you can use CopyOnWriteArrayList instead of ArrayList. When you stash listeners, it is preferable way to use CopyOnWriteArrayList instead of ArrayList.

Upvotes: 2

Ashwinee K Jha
Ashwinee K Jha

Reputation: 9317

The exception indicates that listeners might have been modified from another thread. So you should check if it is being modified without synchronization somewhere else.

Also check if the implementation of onRendition() removes listener from list as that could be another cause if multiple threads are not involved.

Upvotes: 5

Related Questions