集合类的fail-fast机制

fail-fast机制

集合类的fail-fast机制是指集合被多个线程操作时,导致iterator中的数据改变从而抛出异常。

比如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

实例分析

使用ArrayList的iterator进行遍历的时候,下面是ArrayList的iterator的next()方法:

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];
}

checkForComodification()方法表示检测当前ArrayList有没有被其他线程修改,具体原理是通过ArrayList的当前modCount与之前的modCount进行对比(ArrayList没被操作一次,modCount值都会进行一次加一操作)。

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

ArrayList为什么需要进行checkForComodification这个检测呢?其原因是iterator是通过cursor进行遍历的,如果当前ArrayList被修改(不仅有其他线程的事,也算上自己线程),这会导致当前ArrayList的数据与iterator创建时候的不一致(引起数据不一致,和数组越界)。

需要注意的是Object[] elementData = ArrayList.this.elementData;,ArrayList的iterator每进行一次next()操作都会重新加载一次ArrayList数组,我觉得这是为了将iterator与其接口保持一致,还有减少iterator的内存空间,才这么设计的。

so如果将ArrayList数组保存在iterator里面,是不是就可以不用管当前iterator的数据与ArrayList的数据一致性了呢?这就引出了另外一种机制:fail-safe机制。

fail-safe机制

fail-safe机制是指集合被多个线程操作时,不会引起iterator中的数据改变。

package java.util.concurrent;中的集合类都是fail-safe的,比如CopyOnWriteArrayList

static final class COWIterator<E> implements ListIterator<E> {
    /** Snapshot of the array */
    private final Object[] snapshot;
    /** Index of element to be returned by subsequent call to next.  */
    private int cursor;

    private COWIterator(Object[] elements, int initialCursor) {
        cursor = initialCursor;
        snapshot = elements;
    }
}

CopyOnWriteArrayList的COWIterator在构造函数中将CopyOnWriteArrayList数组直接保存在final修饰的Object[]数组中,从而COWIterator中的数据一定不会被修改(final修饰的数组只能赋值一次)。

此外,也能看出Java的泛型真的是通过强制类型转换实现的(先变成Object,然后强制类型转换为<T>的类型)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值