First of all, it is necessary to understand the concept of synchronous modification, which means that one or more threads are traversing a collection, and another thread modifies the data structure of the Collection (add, delete or modify);
1.fail-fast mechanism
The fail-fast mechanism throws Concurrent Modification Exception directly when the collection element is modified when the collection is traversed. There are two situations;
1> In a single-threaded environment
After the collection is created, the structure is modified in the process of traversing it. Note that the remove() method will make expectModcount and modcount equal, so this exception will not be thrown.
2> In a multi-threaded environment
While one thread is traversing an element, another thread makes changes to the element
The principle of fail-fast mechanism verification is to internally maintain an identifier "mode". When the collection data structure is modified, the mode is modified; the next and hasNext methods of each traversal will check whether the "mode" has been modified. Concurrent Modification Exception is thrown
For example, the source code of the ArrayList iteration part
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
2.fail-safe mechanism
The fail-safe mechanism copies a new object every time the collection is modified, so no ConcurrentModificationException is thrown,
There are two problems with the fail-safe mechanism
(1) The collection needs to be copied, a large number of invalid objects are generated, and the overhead is high
(2) There is no guarantee that the data read is the data in the current original data structure.
3. Examples of fail-fast and fail-safe mechanisms
package com.example.springbootDemo.service;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class FailFastExample {
public static void main(String[] args) {
Map<String,String> premiumPhone = new HashMap<String,String>();
premiumPhone.put("Apple", "iPhone");
premiumPhone.put("HTC", "HTC one");
premiumPhone.put("Samsung","S5");
Iterator iterator = premiumPhone.keySet().iterator();
while (iterator.hasNext())
{
System.out.println(premiumPhone.get(iterator.next()));
premiumPhone.put("Sony", "Xperia Z");
}
}
}
package com.example.springbootDemo.service;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
public class FailSafeExample {
public static void main(String[] args) {
ConcurrentHashMap<String,String> premiumPhone =
new ConcurrentHashMap<String,String>();
premiumPhone.put("Apple", "iPhone");
premiumPhone.put("HTC", "HTC one");
premiumPhone.put("Samsung","S5");
Iterator iterator = premiumPhone.keySet().iterator();
while (iterator.hasNext())
{
System.out.println(premiumPhone.get(iterator.next()));
premiumPhone.put("Sony", "Xperia Z");
}
System.out.printf("premiumPhone:"+premiumPhone.toString());
}
}