Reputation: 340
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
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
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