Java.util.ConcurrentModificationException But I am not removing

My below recursive function throws ConcurrentModificationException in continue statement. I have looked at several posts about ConcurrentModificationException and all the problems seem to be related to removing an element from an element, but I am not removing any element in my function.

My function is below:

    public static void getRootedTreeHelper(Node n, boolean[] marked, String spacing){ 

        System.out.println(spacing + "in helper with " + n.getId());
        marked[n.getId()] = true;
        if(n.children.isEmpty())
            return;
        else{
            for(Node child : n.children){
                if(marked[child.getId()])
                    continue; // ConcurrentModificationException is thrown here. 
                else{
                    n.addChild(child);
                    spacing = spacing + "\t";
                    getRootedTreeHelper(child, marked, spacing);
                }
            }
        }
    }

      

As requested: The relevant sections of the Node class are shown below

public class Node {

    private int id;
    ArrayList<Node> children;

    public Node(int id) {
        this.id = id;
        children = new ArrayList<Node>();
    }

    /**
     * add node n to this node children
     * @param n
     */
    public void addChild(Node n) {
        children.add(n);
    }

    // getters and setters()
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

      

Does anyone have any ideas?

Edit solution: Instead of using a for each loop to iterate over all children, I use a for loop.

+3


source to share


2 answers


From the ConcurrentModificationException

Javadoc:

Note that this exception does not always indicate that the object has been simultaneously modified by a different thread . (...) For
For example, if a thread modifies a collection directly while it is iterating over a build using a failover iterator, the iterator will throw this exception.



The error lies in adding a child to the collection and also iterating over it.

The error is only detected by the iterator when it is incremented in the loop for

.

+2


source


If you look at the implementation of the Iterator ArrayList

, it shows that at runtime Iterator.next()

it checks if the size of the collection has changed.

if (i >= elementData.length)
  throw new ConcurrentModificationException();

      

Even using the synchronized version from Collections.synchronizedList(n.children)

would not help as it still uses the same Iterator.



So, if you want concurrent access that modifies the collection, you have a choice:

  • use Iterator.remove()

    to remove the current element,
  • use a version that allows parallel modification, for example, ConcurrentLinkedQueue

    or ConcurrentLinkedDeque

    or
  • use a different one List

    for recording changes than for iterating.

You can try LinkedList

- I haven't read the source in full, but a quick glance at it Iterator

seems like it is immune to additions during iteration.

+4


source







All Articles