Map Collection Fail-Fast Mechanism

In the case of multi-threading, traversing the map collection may cause errors, because the fail-fash mechanism in the collection (the same as Map and List\Set) throws an exception as long as the collection structure changes.

View the Map source code as follows:

 

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

 modCount is an attribute defined by map, which saves the number of times the structure has been modified. The source code can see that modCount is incremented by 1 in both the put and remove(Object) methods:

 

 

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

 

final Entry<K,V> removeEntryForKey(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);
        Entry<K,V> prev = table[i];
        Entry<K,V> e = prev;

        while (e != null) {
            Entry<K,V> next = e.next;
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k)))) {
                modCount++;
                size--;
                if (prev == e)
                    table[i] = next;
                else
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }

        return e;
    }

 

 

The Fail-Fast mechanism is mainly to avoid a series of possible problems caused by the modification of the collection being processed, but in a multi-threaded environment, the program must be controlled not to cause the collection being traversed to be modified.

 

There are two solutions.

 

The first is to synchronize and lock to ensure that only one thread can operate the collection object at the same time. For Map, HashTable can be used to ensure synchronization when the business is suitable.

 

The second way is to clone the collection before traversing the collection, and then manipulate the cloned object. For example, for the Map collection map, you can use Map cloneMap=new HashMap(); cloneMap.putAll(map); to perform a shallow clone, and then traverse the cloneMap collection.

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326627722&siteId=291194637