3

Why does this code cause a ConcurrentModificationException in Java?

public class MainMenuState {
    protected void init() {
        this.addElements(
             new GUIElement()
             .addMousePressed((e, element) -> {
                   this.elements.add(new GUIElement()
                   .addMouseEntered((e, element) -> //...)
             }
        )
   );
}

addElements is defined as:

void addElements(GameElement... elements){
    this.elements.addAll(Arrays.asList(elements));
}

I expect the code to create another GUIElement and add it to list elements when I click the enclosing GUIElement. Instead, when it is clicked, a ConcurrentModificationException is thrown. I understand that ConcurrentModificationException is thrown when a list is modified while elements are being added to it, but mouseEntered isn't called until after elements has been modified.

So how is this error occurring?

The error text:

Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at java.lang.Iterable.forEach(Unknown Source)
at code.state.GameState.render(GameState.java:34)
at code.state.Handler.render(Handler.java:32)
at code.state.Handler.render(Handler.java:28)
at code.frame.GameEngine.render(GameEngine.java:94)
at code.frame.GameEngine.run(GameEngine.java:68)
at java.lang.Thread.run(Unknown Source)

2 Answers 2

5

I don't think there's enough context here to pinpoint exactly the cause of your issue. But one solution would be simply to use:

 List<Object> objList = Collections.synchronizedList(new ArrayList<Object>());

to instantiate the problematic list to simple synchronize access to it.

Sign up to request clarification or add additional context in comments.

Comments

4

I'm assuming you're rendering something to screen in the code.frame.GameEngine.render() method. The problem is you're using a LinkedList which is not thread-safe. Thus, it's possible to add a new GUIElement to elements while code.frame.GameEngine.render() method is iterating over elements (this happens asynchronously). You need to use a thread-safe collection like:

List<GUIElement> elements = Collections.synchronizedList(new LinkedList<GUIElement>());

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.