每周读源码:源码解读fail-fast和fail-safe的实现机制

大家好,这里是IT技术百货,专注于有价值的IT技术知识分享;

今天跟大家分享集合遍历中的fail-fast和fail-safe的实现机制

fail-fast和fail-safe指的是什么

fail-fast和fail-safe指的是利用iterator进行集合遍历时,当集合被修改之后是否抛出异常;

fail-fast机制会抛出异常(ConcurrentModificationException),而fail-safe机制不会抛出异常;

下面截图中的代码默认是fail-fast机制,运行的话会抛出异常:

每周读源码:源码解读fail-fast和fail-safe的实现机制

fail-fast机制抛出异常

fail-safe机制:


每周读源码:源码解读fail-fast和fail-safe的实现机制

failsafe机制 - 不会抛出异常


具体是怎么实现的?

fail-fast机制:

使用fail-fast机制的集合在内部维护了一个字段:modCount ,用来记录这个集合被修改了多少次,比如:增删元素、替换元素、排序等

Iterator迭代器在初始化的时候,会记录下这个 modCount 这个字段值,如下图所示:

每周读源码:源码解读fail-fast和fail-safe的实现机制

初始化记录modCount值

在遍历过程中next、remove、add方法会对这个值进行校验,具体代码如下:

每周读源码:源码解读fail-fast和fail-safe的实现机制

校验逻辑

特别说明:iterator内部的add和remove方法修改集合不会抛异常;iterator内部做了处理。

fail-safe机制:

fail-safe机制实现很简单,就是将原来的集合copy一份,然后基于新拷贝的集合进行遍历;

返回的Iterator实际上是COWIterator,通过源码可以看出COWIterator持有对象的一份快照;


每周读源码:源码解读fail-fast和fail-safe的实现机制

快照源码

之后所有的遍历都是基于这个快照进行的;

灵魂拷问,真的是拷贝了一份新的吗?

通过代码来看,是直接将CopyOnWriteArrayList对象的元素数组赋值给了Iterator,这就说明本质上还是用的一个对象,那为什么不会失败呢?


每周读源码:源码解读fail-fast和fail-safe的实现机制

直接获取CopyOnWriteArrayList对象的数组,并赋值给COWIterator


对比CopyOnWriteArrayList 和 ArrayList的源码可以发现,CopyOnWriteArrayList的add和remvoe操作都是将原数组拷贝到一个新数组里面,也就是不会改变原数组,而ArrayList事先声明了一个大容量数组,当添加或者删除操作时尽量在原数组上进行;


每周读源码:源码解读fail-fast和fail-safe的实现机制

CopyOnWriteArrayList的add操作


每周读源码:源码解读fail-fast和fail-safe的实现机制

CopyOnWriteArrayList的remove操作

每周读源码:String类的equals是怎么实现的(阿里面试手写代码)

感谢浏览阅读,如果觉得内容有价值欢迎点赞,收藏,转发;喜欢请关注“IT技术百货”


分享到:


相關文章: