Concurrent Modification exception

2019-01-01 05:42发布

I have this little piece of code and it gives me the concurrent modification exception. I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.

import java.util.*;

public class SomeClass {
    public static void main(String[] args) {
        List<String> s = new ArrayList<>();
        ListIterator<String> it = s.listIterator();

        for (String a : args)
            s.add(a);

        if (it.hasNext())
            String item = it.next();

        System.out.println(s);
    }
}

9条回答
皆成旧梦
2楼-- · 2019-01-01 06:19

to understand this lets look at source of HashMap implementation:

public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable{

which contains HashIterator as below:

private abstract class HashIterator {
    ...
    int expectedModCount = modCount;
    ...

    HashMapEntry<K, V> nextEntry() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        .... 
        }

every time you create a iterator:

  • a counter expectedModCount is created and is set to value of modCount as entry checkpoint
  • modCount is incremented in cases of use put/get (add/remove)
  • nextEntry method of iterator is checking this value with current modCount if they are different concurrent modification exception is throw

to avoid this u can:

  • convert map to an array (not recommended for large maps)
  • use concurrency map or list classes (CopyOnWriteArrayList / ConcurrentMap)
  • lock map (this approach removes benefits of multithreading)

this will allow you to iterate and add or remove elements at the same time without rising an exception

Concurrency map/list iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

More info on CopyOnWriteArrayList

查看更多
流年柔荑漫光年
3楼-- · 2019-01-01 06:20

You are not allowed to continue iterating over an iterator after the underlying list is modified. Here you create the iterator before adding a few items to s, and then proceed to do a hasNext() and a next() on it after the additions, leading to the ConcurrentModificationException

查看更多
泛滥B
4楼-- · 2019-01-01 06:22

Have a look at oracle documentation page.

public class ConcurrentModificationException
extends RuntimeException

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. 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.

In your case, you have modified the collection after creating the iterator and hence you have encountered the exception.

If you change your code as per Stephen C answer, you won't get this error.

查看更多
登录 后发表回答