raggnic
raggnic

Reputation: 340

Unclear ConcurrentModificationException on separate lists

in a class I've those 2 methods:

public void notifyResult(List<Road> result) {
    ArrayList<RoadOverlay> tempRoads = new ArrayList<>();

    for(Road road:result){
    // Computes and stores the overlays
    // ...
        tempRoads.add(new RoadOverlay());
    }
    //switch field when update is done
    this.positions = tempRoads;
    }
}

private void drawRoadsVO(GL gl) {
    // keep a reference on the current instance of the field 
    // to avoid concurrent modification in notifyResult
    ArrayList<RoadOverlay> positionsCopy = this.positions;
    int vertexCount = 0;
    for (RoadOverlay road : positionsCopy) { //ConcurrentModificationException here
             // ...
        }
}

Both method run in separate threads. Inside rendering i make no change on the list, and to my understanding i work on separate lists so how could this produce CME? I'm struggling on this one, and any clue would be welcome. As far as possible I try to avoid penalty of using synchronisation.

regards

Edited a comment in the code

Upvotes: 1

Views: 60

Answers (2)

dezhik
dezhik

Reputation: 1030

It is usually better to make full copy of a list

ArrayList<RoadOverlay> positionsCopy = new ArrayList<Integer>(this.positions);

As for ConcurrentModificationException, your code looks fine, may be you are modifying current this.positions in some other class methods? Note that your this.positions variable should be declared as volatile.

Here is next() method of ArrayList iterator

public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
        throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
        throw new ConcurrentModificationException();
    cursor = i + 1;
    return (E) elementData[lastRet = i];
}

final void checkForComodification() {
    if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}

ConcurrentModificationException could be thrown only in case then list's elementData is structurally modified

Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.

Upvotes: 1

yugo
yugo

Reputation: 198

the problem is inside drawRoadsVO method your var positionsCopy is not actually a copy, but a reference to the same object this.positions.

In order to make actual copy you should do

ArrayList<RoadOverlay> positionsCopy = new ArrayList(this.positions);

Upvotes: 1

Related Questions