Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

preface

  • In the past, when I read the JDK source code, I will find that there is a fast failure and failure safety mechanism implementation of the application.
  • Fast failure and fail-safe mechanism is actually a design idea, and its application scenarios are not only in Java collection class, but also in many open source frameworks. Dubbo’s cluster fault-tolerant mechanism, in addition to fast failure and fail-safe mechanism, also has fail-failover, fail-safe mechanism, parallel call multiple services mechanism.
  • I don’t know much about the Dubbo framework, but I’ll focus on implementing fast failures and fail-safe mechanisms in JDK collections.

Quick failure mechanism

  • First look at the interview questions:
public static void main (String[] args) {
   ArrayList<Integer> list = new ArrayList<>();
   list.add(1);
   list.add(2);
   for (Integer num : list) {
       if (2 == num) {
           list.remove(num);
       }
   }
   System.out.println(list);
}
Copy the code
  • What is the result of this code execution?
  • Obviously this is not difficult, actually will not print, directly throw exceptions: Java. Util. ConcurrentModificationException

  • Arraylist.java: line 909 (arrayList.java :909)
final void checkForComodification() { if (modCount ! = expectedModCount) throw new ConcurrentModificationException(); }Copy the code
  • When the condition modCount! = expectedModCount, namely will throw ConcurrentModificationException.
  • So let’s see what these two parameters mean. And in which case modCount will be satisfied! = expectedModCount.

modCount

  • Take a look at the modCount field’s remarks:

  • My English is not good enough to translate the whole paragraph, focusing on the circled position in the picture shows that it fails -fast, and increases it in the add and remove methods.

  • The above image shows modCount increment in the add and remove methods, respectively

expectedModCount

  • In one of the inner Itr classes in the collection, there is an attribute, expectedModCount, which changes the expected number of times

  • The first assignment when an Itr class object is initialized:
int expectedModCount = modCount;
Copy the code

  • If you call remove on an Itr object, the assignment is done again.

modCount ! = expectedModCount

  • First remove the Java syntax sugar mechanism and look at the class file after the current class is loaded

  • In the current foreach loop deletion scenario, foreach will eventually be compiled to use Iterator objects.
  • The Iterator does not pass the test when the Iterator is used to get the elements, and the test does not pass the test when the Iterator is used to get the elements. ConcurrentModificationException.
  • If the element is removed using the remove method of the Iterator, the expectedModCount is assigned to make sure that modCount == expectedModCount. The Iterator needs to be locked for concurrency
Note: The principle of pre-detection of exceptions is actually the embodiment of the fast failure mechanism. When the iterator accesses the elements of the collection, if there is any change in the elements of the collection, the exception will be thrown immediately.Copy the code

Failsafe mechanism

  • Unlike a quick failure, a security failure is an exception that occurs during the invocation, which is not thrown, but is logged or printed, and the subsequent process continues.
  • The security failure mechanism is used in all concurrent collections of java.util.Concurrent. Instead of traversing the collection over the original collection, a copy of the original collection is directly traversed over the replicated collection contents
  • Copying the contents of the original collection avoids the quick failure mechanism, but increases memory footprint, and consistency is not guaranteed, only the final consistency of the data is guaranteed.
  • Concurrent collections under java.util.concurrent can be executed concurrently in multiple threads, because the original collection content is not operated, so the execution process does not affect each other, and the subsequent flow will be executed.
public static void main (String[] args) {
    CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
    list.add(1);
    list.add(2);
    final Iterator<Integer> iterator = list.iterator();
    while (iterator.hasNext()) {
        Integer next = iterator.next();
        if (2 == next) {
            list.remove(next);
        }
    }
    System.out.println(list);
}
Copy the code
  • This will print normally

The last

  • If there is any problem with the above expression, please point out!
  • Finally, learn modestly and make progress together