java中fail-fast 和 fail-safe的区别

首先要弄明白同步修改的概念,指的是一个或者多个线程正在遍历一个集合,此时另外一个线程修改了Collection的数据结构(添加,删除或者修改);java

1.fail-fast机制spring

fail-fast机制在集合被遍历时,若是集合元素被修改,直接抛出Concurrent Modification Exception,有两种状况;springboot

1>单线程环境下数据结构

集合被建立后,在遍历它的过程当中修改告终构。注意 remove()方法会让expectModcount和modcount 相等,因此是不会抛出这个异常。多线程

2>多线程环境下this

一个线程在遍历元素时,另外一个线程对元素进行了修改线程

fail-fast机制校验的原理是内部维护了一个标识“mode”,当集合数据结构被修改时,修改mode;在每次遍历的next和hasNext方法会去检验“mode”是否被修改,若修改则抛出Concurrent Modification Exceptioncode

例如ArrayList迭代部分的源码对象

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机制element

fail-safe机制在每次对集合进行修改时会复制一个新的对象,所以不会抛出ConcurrentModificationException,

fail-safe机制有两个问题

(1)须要复制集合,产生大量的无效对象,开销大

(2)没法保证读取的数据是目前原始数据结构中的数据。

3.fail-fast和fail-safe机制例子

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());
    }
}
相关文章
相关标签/搜索