Fail-fast
表示快速失败,在集合遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出 ConcurrentModificationException 异常,从而导致遍历失败,像这种情况
定义一个 Map 集合,使用 Iterator 迭代器进行数据遍历,在遍历过程中,对集合数据做变更时,就会发生 fail-fast。java.util 包下的集合类都是快速失败机制的, 常见的的使用 fail-fast 方式遍历的容器有HashMap 和 ArrayList 等。
Fail-safe
Fail-safe,表示失败安全,也就是在这种机制下,出现集合元素的修改,不会抛出 ConcurrentModificationException。原因是采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到
定义了一个 CopyOnWriteArrayList,在对这个集合遍历过程中,对集合元素做修改后,不会抛出异常,但同时也不会打印出增加的元素。java.util.concurrent 包下的容器都是安全失败的,可以在多线程下并发使用,并发修改。常见的的使用 fail-safe 方式遍历的容器有 ConcerrentHashMap 和CopyOnWriteArrayList等。
总结
fail-fast
机制是
Java
集合(
Collection
)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生 fail-fast
事件。 例如:当某一个线程 A
通过
iterator
去遍历某集合的过程中,若该集合的内容被其他线程所改变了,那么线程 A
访问集合时,就会抛出
ConcurrentModificationException
异常,产生
fail-fast
事件。这里的操作主要是指 add
、
remove
和
clear
,对集合元素个数进行修改。
解决办法:建议使用
“java.util.concurrent
包下的类
”
去取代
“java.util
包下的类
”
。
fail-fast
机制可以这么理解:在遍历之前,把 modCount
记下来
expectModCount
,后面
expectModCount
去 和 modCount
进行比较,如果不相等了,证明已并发了,被修改了,于是抛出ConcurrentModificationException 异常。