I used synchronized list, and i still get ConcurrentModificationException [duplicate]
Asked Answered
Q

3

15

I'm using Vector instead of ArrayList to make a list safe in multi-threaded enviroment. But I keep getting ConcurrentModificationException when I trying to add items to the Vector while iterating it. Why is that and how can I prevent it?

Quennie answered 15/3, 2013 at 16:44 Comment(1)
concurrent != parallel. You can get a ConcurrentModificationException with a single thread.Melvamelvena
L
9

You cannot modify a Vector while iterating over it. Store the items to add in a separate vector, and move them to the Vector when the loop is finished or loop over a copy of the original Vector.

ADDED: To get a mutex around the Vector in java, do this in both functions:

synchronized (list) {
  // modifying list
}

and:

synchronized (list) {
  // iterating over list
}

Of course I've assumed that the list is named list

Lightship answered 15/3, 2013 at 16:46 Comment(11)
Side note: this holds true even in single-threaded programs.Paco
what do you mean it holds true in single-threaded programs?Quennie
You can never modify the list while iterating over it. Even in single threaded programs. Modifying the underlying list invalidates the iterator.Lightship
so what the purpose of synchronized collections in this case?Quennie
None. It only synchronizes direct modifications and reads of the list. Which, in at least Java, does not include Iterators of the list. You need to use a mutex instead - locked for the entire duration of the loop, and which is locked while any other operation is performed on the list.Lightship
To prevent another thread from modifying the current thread's view of the list. Note that this does not imply the list is immutable.Trant
"Store the items to add in a separate vector, and move them to the Vector when the loop is finished or loop over a copy of the original Vector." => or use an existing class of the standard JDK which does exactly that: a CopyOnWriteArrayListKetch
@Ketch That is not what that class does. It copies the list, throwing away the old one. What I propose is to wait with appending new items until the iterator finished.Lightship
I have one method that adds items to the Vector, and another method itareting on the Vector. I synchronized both, is that good idea?Quennie
Synchronizing methods will not help - as it only prevents that function from being run concurrently. It does not help with two different functions, they can still be executed concurrentlyLightship
There is also recommended to declare synchronizing object as final, to sure that it's reference should be changed.Dido
T
2

if you want to add items as you iterate, you'll want to use a ListIterator. by using Vector, you're not bypassing this rule (obviously), so I would recommend using the ArrayList instead.

Thorlay answered 15/3, 2013 at 16:47 Comment(2)
I don't think it is safe to add while iterating with a ListIterator if more than one thread is involved.Ketch
@assylias, I misunderstood the question, I suppose. I was just addressing the ConcurrentModificationException.Thorlay
K
2

If you need to iterate and add concurrently to your list, you should use a concurrent list, such as CopyOnWriteArrayList. Note that if you write a lot to the list it will not be very efficient.

Otherwise, if you use a Vector or a synchronizedList, you need to hold the list's lock while iterating. That will prevent the exception but it will also prevent concurrency...

Ketch answered 15/3, 2013 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.