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

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

1.fail-fast机制

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

1>单线程环境下

集合被创建后,在遍历它的过程中修改了结构。注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

2>多线程环境下

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

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

例如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机制

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

扫描二维码关注公众号,回复: 94839 查看本文章

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());
    }
}

猜你喜欢

转载自my.oschina.net/u/2596536/blog/1623793
今日推荐