0

I'm trying to iterate through a Integer ArrayList and getting the value at each element, but I'm getting an error at the int value = ....

Not sure whats happening. Please advise.

Iterator<Integer> listItr = executeList.iterator(); // iterator for the execute list 
    while (listItr.hasNext()) { // iterate through list and do work!
        int robIndex = listItr.next();
        int timer = fakeRob.exeCountDown(robIndex); // decrement first then return timer
        if (timer == 0) {// check if instr finished execution
            System.out.println("timer expired. fire");
            executeList.remove(executeList.indexOf(robIndex)); // 1. remove instr from exeList
            transitState(robIndex, EX, WB); // 2. transit from EX state to WB state
            int tag = fakeRob.getTag(robIndex); // get producer tag
            regFile.setRdy(tag); // 3a. set register file ready flag for this tag
            fakeRob.wakeUp(tag); // 3b. wake up instructions with this tag
        }
    }

Error:

java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at sim.execute(sim.java:180)
at sim.<init>(sim.java:71)
at sim.main(sim.java:270

Thanks,

Hank

Hank Liu
  • 85
  • 1
  • 3
  • 9
  • 4
    Are you modifying the list as you're iterating over it? Is another thread accessing the same list at the same time? – I82Much May 05 '12 at 23:17
  • From a quick glance, it seems this code snippet with an iterator shouldnt be throwing that exception. Are you sure you pasted the correct code? – CoolBeans May 05 '12 at 23:18
  • I recently participated in a similar discussion in http://stackoverflow.com/a/10432084/697630, perhaps it helps clarify why this is happening in your code. – Edwin Dalorzo May 05 '12 at 23:24
  • Could you please paste more code perhaps in pastebin so that we can see what's going on? The code as is shouldn't throw the `ConcurrentModificationException`. – CoolBeans May 05 '12 at 23:26
  • Add the code for *do some stuff with value at each iteration*, are you removing the item from list? are you adding new items to the list? – Amir Pashazadeh May 05 '12 at 23:47
  • I've revised my post with the whole method. Based on the responses, I suppose the prob is due to the self-modification... I'm just trying to figure out a way around it. I have to iterate through the list and remove the ones that are "matches". This method is suppose to simulate the execution stage of a pipeline processor using tomasulo algorithm. Any help is appreciated, thanks – Hank Liu May 06 '12 at 03:44
  • Based on the code you've written, you could probably use `listItr.remove()` to safely remove elements during the iteration. – Louis Wasserman May 06 '12 at 05:43

2 Answers2

1

If the local variable value is the thing that you "do some stuff with", and you are not modifying the list, then some outside thread is modifying the list while you are in there.

Otherwise, see the link provided by @edalorozo for some ideas

EDIT ADDED

I never use the iterator.remove() idiom, because I never got all that familiar with the iterator idiom. And always mixed it up with the short lived and poorly implemented Enumerator stuff. Before the enhanced for loop, I typically looped using the very old fashioned for (int i-0; i<foo.length; i++) style. And not all Iterators support remove(), so what's the point?

Therefore, I got "used to" the "collect everything and delete it afterwards" style, even when I now use the enhanced for loop. In your code, that would be:

ArrayList <Integer> toBeRemoved = new ArrayList <Integer>();
for (Integer robIndex : executeList) {
   // note, I distrust auto-unboxing, (see all the Java Puzzlers books!)
   // so I'd probably add an explicit unbox here
   int robIndexi = robIndex.intValue();

   int timer = fakeRob.exeCountDown(robIndexi); // decrement first then return timer
   if (timer == 0) {// check if instr finished execution
      toBeRemoved.add(robIndex);
      // all that other stuff here...
   }
}

// remove everything now
executeList.removeAll(toBeRemoved);
Community
  • 1
  • 1
user949300
  • 15,364
  • 7
  • 35
  • 66
  • Thanks for your comment. The list is actually being modified. I've revised my post to add the whole method if you could take another look and let me know what you think. Thanks – Hank Liu May 06 '12 at 03:39
  • See comment below @Matt answer. – user949300 May 06 '12 at 15:51
1

Perhaps if you put what it is you're doing inside the loop it would help. If you're trying to remove an element from the list, you need to call listItr.remove() to do it. In general, you should not be calling any functions in the loop which modify the list (ie. add(), set(), etc...).

The following code would trigger this

Iterator<Integer> it = executeList.iterator();
while (it.hasNext()) {
  Integer i = it.next();
  executeList.remove(i);
}

The proper way to do it would be:

Iterator<Integer> it = executeList.iterator();
while (it.hasNext()) {
  Integer i = it.next();
  it.remove();
}

Also other threads (as mentioned above) could be the issue. Remember, iterators are backed by the list itself in all the java supplied collections. So if another thread modifies the list while you'e iterating, you'll run into this.

Matt
  • 11,523
  • 2
  • 23
  • 33
  • This is a single threaded program. I will go ahead and give your solution a try and see what happens. I'm curious though, what is going behind the scene for executeList.remove(i) vs it.remove(i)? – Hank Liu May 06 '12 at 05:32
  • The Iterator knows all about itself, so it isn't "surprised" when it deletes an entry. Though it obviously knows something about the list, when the list removes a value, the iterator detects that the list has changed (via a counter that gets incremented as things are changed) but doesn't know how to correct for it, so it throws the ConcurrentModificationException. – user949300 May 06 '12 at 15:50
  • I see. In the "proper way" posted by Matt. It will always begin removing from the first element in the list right? – Hank Liu May 06 '12 at 16:09
  • Yes. Javadocs for `List.remove()` say "Removes the first occurrence..." – user949300 May 09 '12 at 00:33