1

I have next code in background thread

private List<IStartAction> mActions = Collections.synchronizedList(new ArrayList<IStartAction>()); 

protected void removeNonApplicableActions() {
        Iterator<IStartAction> iterator = mActions.iterator();
        while (iterator.hasNext()) {
            IStartAction action = iterator.next();
            if (!action.isApplicable()) {
                iterator.remove();
            }
        }
    }

When i run this in main thread got ConcurrentModificationException into iterator.next(). Why is this happening? I use thread-safe collection and remove items through iterator. Collection used in only this thread.

8
  • synchronized means that you can modify list in more than 1 thread under specific conditions (please see javadoc for synchronizedList() method). Here is a different issue, you are iterating and removing at the same time. Please use listIterator instead of plain iterator. Use listIterator() method. Commented May 5, 2015 at 20:23
  • 3
    Could you provide a minimal working example of your code so that we can reproduce the problem? Commented May 5, 2015 at 20:25
  • 2
    ConcurrentModificationException isn't necessarily indicating you have multiple threads modifying your list, it's that you are concurrently iterating through your list and modifying it at the same time. Commented May 5, 2015 at 20:28
  • This seems weird/buggy. MCVE please. Commented May 5, 2015 at 20:33
  • 2
    What does isApplicable() do? Does it modify mActions in any way? Commented May 5, 2015 at 20:34

1 Answer 1

2

Thread safety for a synchronized collection only applies to one method call. Between method calls the lock is released and another thread can lock the collection. If you perform two operations, anything could happen in the meantime, unless you lock it your self. e.g.

// to add two elements in a row, you must hold the lock.
synchronized(mAction) {
    mAction.add(x);
    // without holding the lock, anything could happen in between
    mAction.add(y);
}

Similarly to iterate over a synchronized collection, you have to hold the lock, otherwise anything could happen between method calls to the iterator.

synchronized (mAction) {
    for(Iterator<IStartAction> iter = mActions.iterator(); iter.hashNext();) {
        IStartAction action = iter.next();
        if (!action.isApplicable()) {
            iter.remove();
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.