fail-fast 和 fail-safe

 我来答
一袭可爱风1718
2022-06-08 · TA获得超过1.2万个赞
知道大有可为答主
回答量:6402
采纳率:99%
帮助的人:35.8万
展开全部

当一个或多个线程正在遍历一个集合(Collection),此时另一个线程修改了这个集合(添加,删除或修改)就称为并发修改。

.

官方文档在HashMap集合中对fail-fast的解释

意思就是:这个迭代器(Iterator)被创建后,除了迭代器自身的方法(remove)可以改变集合的 结构 ,其他情况改变了集合的结构,都将跑出一个 ConcurrentModificationException 异常。

从上面的源码,可以发现迭代器在执行 next() 等方法的时候,都会调用一个方法 checkForComodification() ,而这个方法就是检查 modCount 是否等于 expectedModCount ,如果不等于就抛出 ConcurrentModificationException 异常。

expectedModCount 这个变量的值在对象被创建的时候就赋予了一个固定的值 modCount ,这个值是不变的,当迭代器遍历元素的时候,如果 modCount 发生了改变,那就会抛出异常。

查看源码可以发现,当对集合进行增删操作都会 modCount++ 。

所以当我们对集合的元素的个数做出修改(添加、删除)的时候, modCount 的值就会发生改变,但对元素进行修改则不会改变 modCount 的值。

保证在并发修改的时候,对所有会影响到 modCount 发生改变的地方,加上同步锁(synchronized),或者使用同步类容器 Collections.synchronizedList 。

.

fail-safe: 任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出 ConcurrentModificationException 异常。

两个问题:

从源码可以看到,在对集合进行添加和删除元素的时候都进行加锁,然后让当前下标的元素添加或删除,最后将原数组的地址指向新的数组,完成复制。这里涉及到 CopyOnWrite机制

这样做不会出现 fail-fast ,但是对集合进行增删操作都需要加锁,影响效率。同时增加对象容量可能会导致 OOM 。

在遍历过程中,集合的元素并不一定是最终的元素集合,所以只能保证最终一致性。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式