This is my class:
public class AComplicatedclass {
private List<Connection> activeConnections;
private Lock lock = new ReentrantLock();
public void printConnections() {
lock.lock();
for(Connection c : activeConnections){ //exception happens here
...prints details about connection
activeConnections.remove(c);
}
lock.unlock();
}
private class MyThread extends TimerTask {
public void run() {
lock.lock();
...can alter activeConnections....
lock.unlock();
}
}
}
As you can see a lock object should prevent problems due to concurrent access to that shared array. Nevertheless, when printConnections()
method is called, I get a ConcurrentModificationException
in that for
.
How come? There is no concurrent modification at all!
Most probably you modify your collection inside the for-loop. As the documentation on ConcurrentModificationException states
For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
The reason an iterator throws the exception is that it can no longer be determined which element is to be returned next.
So if you want to modify your collection you need to either switch to something like CopyOnWriteArrayList or use the Iterator explicitly as in
Iterator<Connection> iterator = activeConenctions.iterator();
while(iterator.hasNext()) {
Connection c = iterator.next();
if(/* what ever */) {
iterator.remove();
}
}
Editing a list during a foreach iteration almost always results in a ConcurrentModificationException, even if your application is single threaded.
If you need to remove items during the iteration, use an iterator:
final Iterator<Connection> iterator = activeConnections.iterator();
while(iterator.hasNext()) {
final Connection connection = iterator.next();
// ...prints details about connection
iterator.remove();
}
According to the Javadoc of ConcurrentModificationException
:
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
This has nothing to do with unsynchronized access.
Some examples of problematic operations:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.