快速失败(fail-fast)和安全失败(fail-safe)了解吗?

快速失败(fail-fast):快速失败是Java集合框架的一种错误检测机制。

  • 当使用迭代器遍历集合对象时,如果在遍历过程中,其他线程对集合对象的内容进行了修改(增加、删除、修改),就会抛出

ConcurrentModificationException异常。

  • 原理:迭代器在遍历时直接访问集合的内容,并且使用一个modCount变量来记录集合被修改的次数。在每次迭代器调用hasNext()next()方法之前,都会检查modCount的值是否与期望值相等,如果不相等,就抛出异常终止遍历。
  • 注意:异常抛出的条件是modCount != expectedModCount。如果集合在修改后将modCount恰好又设置为了期望值,那么异常就不会被抛出。因此,不能依赖于此异常来进行并发操作的编程,这个异常只是用于检测并发修改的bug。
  • 场景:Java.util包中的集合类都是快速失败的,在多线程环境下进行并发修改(在迭代过程中修改)是不安全的,比如ArrayList类。

安全失败(fail-safe)

  • 采用安全失败机制的集合容器在遍历时不直接访问集合的内容,而是先复制原有集合的内容,然后在复制的集合上进行遍历。
  • 原理:由于迭代器遍历的是集合的拷贝,所以在遍历过程中对原集合的修改不会被迭代器检测到,因此不会触发ConcurrentModificationException异常。
  • 缺点:基于拷贝内容的优点是避免了ConcurrentModificationException异常,但迭代器无法访问修改后的内容。即,在遍历期间,原集合发生的修改对迭代器是不可见的。
  • 场景:Java.util.concurrent包下的容器类都是安全失败的,可以在多线程环境下并发使用和修改,例如CopyOnWriteArrayList类。

标签: java, Java面试题, Java问题合集, Java编程, Java问题精选, Java常见问题