Do you really understandfail-fastfail-safe

Good morning to my friends ~😝 already Friday!

I wanted to continue talking about this ConcurrentHashMap, but suddenly I found these features in the source code, which should be very useful for your interview! Welcome correction! 😋


Introduction to the

The fail-fast file in the java.util package fails quickly ~ 😝

The fail-safe file in the java.util.concurrent package fails ~ 😝

If the set data structure is found to be changed during iteration (modCount! Throw ConcurrentModificationException = expectedModCount), will be

Friends can refer to the following code for a simple experiment ~ 😋

fail-fastThe experimental code

The experimental object is Hashtable, here using JDK1.7 writing method ~

Because the blogger is still trying to figure out how ConcurrentHashMap will differ in 7 and 8 below 😝

class E implements Runnable{

    Hashtable<String, String> hashtable;

    public E(Hashtable<String, String> hashtable) {
        this.hashtable = hashtable;
    }

    private void add(Hashtable<String, String> hashtable){
        for (int i = 0; i < 10000000; i++) {
            hashtable.put("a".""+i); }}@Override
    public void run(a) { add(hashtable); }}public class D {


    public static void main(String[] args) {
        Hashtable<String, String> hashtable = new Hashtable<String, String>();
        hashtable.put("1"."2");
        hashtable.put("2"."2");
        hashtable.put("3"."2");
        hashtable.put("4"."2");
        hashtable.put("15"."2");


        new Thread(new E(hashtable)).start();

        Set<Map.Entry<String, String>> entries = hashtable.entrySet();
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while(iterator.hasNext()){ System.out.println(iterator.next()); iterator.remove(); }}}Copy the code

The effect is shown in figure:

Triggering principle:

When the collection data structure changes, the two values are not equal, so the exception ~ is thrown.

Conclusion:

althoughHashTableThread-safe, but it doesfail-fastMechanism, so in the case of multi-threaded iteration can not modify its data structure!fail-fastThe mechanism does not allow concurrent modification!

fail-safeThe experimental code

class E implements Runnable{

    ConcurrentHashMap<String, String> concurrentHashMap;

    public E(ConcurrentHashMap<String, String> concurrentHashMap) {
        this.concurrentHashMap = concurrentHashMap;
    }

    private void add( ConcurrentHashMap<String, String> concurrentHashMap){
        for (int i = 0; i < 100000; i++) {
            concurrentHashMap.put("a"+i,""+i); }}@Override
    public void run(a) { add(concurrentHashMap); }}public class D {



    public static void main(String[] args) {

        ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<String, String>();

        concurrentHashMap.put("1"."2");
        concurrentHashMap.put("2"."2");
        concurrentHashMap.put("3"."2");
        concurrentHashMap.put("4"."2");
        concurrentHashMap.put("15"."2");

        new Thread(new E(concurrentHashMap)).start();
        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Set<Map.Entry<String, String>> entries = concurrentHashMap.entrySet();


        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry);
// There is no need to call iterator to removeconcurrentHashMap.remove(entry.getKey()); }}}Copy the code

The effect is as follows:

The code runs, thread A adds data, thread B iterates through its data, and deletes it.

As you can see, there is no error ~, but it does not guarantee that all values will be iterated over.

Do you feel the slightest sense of security failure ~ 😄

Ha, ha, ha It features 👉 allowing concurrent modification, ConcurrentModificationException, but cannot guarantee to get the latest values

Do you have any doubts after reading the above experimental code

(· ∀ · (· ∀ · *)

Why can it call its ownremove?

Let’s see what happens when we use this iterator.

Source code go ~

Take a look at the following four pictures

The process of creating iterators

,

As you can see from Figure 1, an EntryIterator is created, which in turn inherits the HashIterator, and when initialized, calls the parent class’s constructor first.

As you can see from Figure 3, when a HashIterator is initialized, it calls the advance method (concurrentHashMap is not expanded here). It calls unsafe. getObjectVolatile.

It is used to force property values from main memory.

Compare a HashMap or HashTable to the Entry[]~. 🐷

I wonder if you can get this point ~

Ha ha ha let me nag nag ~ 😝

4ye came across this picture while searching the Internet for the difference between Fail-fast and Fail-safe.

In almost all said fail – safe will copy the original collection, and then on the collection of reproduction, and then say this is not going to throw ConcurrentModificationException.

But this statement is not exact ~ 😝 it should describe the case for the CopyOnWriteArrayList or CopyOnWriteArraySet case (the source code below says ~).

CopyOnWriteArrayListThe source code

You can see that the snapshot pointer always points to the original array (when you create the iterator).

When you add data, it copies the original array, makes changes to the copied array, and then sets it back in. You can see that the original array is not changed at all, so the data in the iterator is unaffected ~😝

conclusion

Fail-safe is also case-by-case.

  1. If it isCopyOnWriteArrayListorCopyOnWriteArraySet, it belongs toThe condition of copying an original set and then operating on the copied setSo you’re not going to throw thisConcurrentModificationException.
  2. If it’s this oneconcurrentHashMap😄 it operates directly on the bottom layer, callUNSAFE.getObjectVolatileDirectly,Force property values from main memoryI’m not going to throw thisConcurrentModificationException.
  3. There is no guarantee that the traversal will get the latest value ~

Now answer the above question why can remove ~

removeThe source code of

In the red box, pred is null, indicating the header of an array. SetEntryAt is called, as in the UNSAFE 😋 and setNext

PutOrderedObject UNSAFE. PutOrderedObject

Sequential (delayed) forcing updates of data to main memory. (Not immediately detected by other threads)

This has to do with Java’s JMM (Java Memory model)! Bury a pit 🕳, behind write concurrent time more ~ 😝

conclusion

Java. Belong to fail – fast under the util package, it is not allowed in the characteristics of concurrent modification, if concurrent modification leads to throw ConcurrentModificationException in iterative process, trigger point is modCount! = expectedModCount 😝

The fail-safe under the java.util.concurrent package allows concurrent modification, but there is no guarantee that the latest values will be retrieved during iteration. 😋 Also, concurrentHashMap uses the UNSAFE class to retrieve data directly from main memory, or to update data directly to main memory. CopyOnWriteArrayList or CopyOnWriteArraySet, Just copy the original set, and then operate on the copied set. It’s a different operation

Welcome attention, make a friend!! (•̀ ω •́)y

Java4ye is a programmer who sends technical articles on weekdays and chats about emotions and other non-technical topics on rest days. Nice to meet you!! 😝

Java4ye public account: welcome to pay attention to bloggers drop personal public account ~ here to prepare a series of learning resources for you, as well as a variety of plug-ins, software oh 😋

Let’s start this unexpected meeting! ~

Welcome to leave a message! Thanks for your support! O (≧ ヾ del ≦ *)