modCount字段在其外部类Hashtable中,注释的大概意思是:这个数字记录了,对hashtable内部结构产生变化的操作次数。如rehash()、put(K key, V value)中,都会有modCount++。
expectedModCount字段在Enumerator类中,并在Enumerator(迭代器)初始化时,赋予modCount的值。其注释的主要内容为:用于检测并发修改。
其值在迭代器的remove()方法中,与modCount一同自增(见上述代码中remove()方法中第22、23行)。
于是真相浮于水面:在获得迭代器时,expectedModCount与modCount值相等,但迭代的同时,第55行的cacheMap.remove(key)使modCount值自增1,导致modCount != expectedModCount,于是抛出ConcurrentModificationException异常。
结果由上面的结论得出:
在Hashtable迭代的过程中,除迭代器中的操作外,凡对该map对象有产生结构变化的操作时,属于并发修改。迭代器将不能正常工作。
这就是此类Hashtable在遍历时,抛出ConcurrentModificationException异常的来由,用加锁同步两个操作不是问题所在。
本文问题解决方法很简单:将55行的使用map调用删除对象
55 cacheMap.remove(key);
改为在迭代器中删除对象
55 i.remove();
即可。
也以此推断出此类异常的解决方式:
要么不要在迭代的时候进行rehash()、put(K key, V value)、remove(Object key)等会对map结构产生变化的操作;要么就在迭代器中做可能的操作。