转自:
http://www.java265.com/JavaJingYan/202206/16540696313601.html
下文笔者讲述fail-fast和fail-safe的区别说明,如下所示同步修改简介说明
- 同步修改(并发修改)指:
- 当一个或多个线程正在遍历一个集合Collection
- 此时另一个线程修改了这个集合的内容(添加,删除或修改)
复制代码 fail-fast机制
- fail-fast机制:
- 在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception
- fail-fast:
- 会在以下两种情况下抛出ConcurrentModificationException
- 1.单线程环境
- 集合被创建后,在遍历它的过程中修改了结构。
- 注意:
- remove()方法会让expectModcount和modcount相等,所以是不会抛出这个异常
- 2.多线程环境
- 当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改
- 注意事项:
- 迭代器的快速失败行为无法得到保证,
- 因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证
- 快速失败迭代器会尽最大努力抛出 ConcurrentModificationException
- 因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测bug
复制代码 fail-fast机制检测方法分享
- 迭代器在遍历过程中是直接访问内部数据的
- 因此内部的数据在遍历的过程中无法被修改
- 为了保证不被修改,迭代器内部维护了一个标记"mode",
- 当集合结构改变(添加删除或者修改)
- 标记"mode"会被修改,而迭代器每次的hasNext()和next()方法都会检查该"mode"是否被改变
- 当检测到被修改时,抛出Concurrent Modification Exception
- 下面看看ArrayList迭代器部分的源码
- private class Itr implements Iterator<E> {
- int cursor;
- int lastRet = -1;
- int expectedModCount = ArrayList.this.modCount;
-
- public boolean hasNext() {
- return (this.cursor != ArrayList.this.size);
- }
-
- public E next() {
- checkForComodification();
- /** 省略此处代码 */
- }
-
- public void remove() {
- if (this.lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
- /** 省略此处代码 */
- }
-
- final void checkForComodification() {
- if (ArrayList.this.modCount == this.expectedModCount)
- return;
- throw new ConcurrentModificationException();
- }
- }
复制代码 fail-safe机制
- fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException
- fail-safe机制有两个问题
- 1.需要复制集合,产生大量的无效对象,开销大
- 2.无法保证读取的数据是目前原始数据结构中的数据
复制代码 fail-fast和fail-safe示例
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
-
- public class FailFastExample
- {
- public static void main(String[] args)
- {
- Map<String,String> map = new HashMap<String,String>();
- map.put("test", "test");
- map.put("test2", "test2");
- map.put("test3","test3");
-
- Iterator iterator = map.keySet().iterator();
-
- while (iterator.hasNext())
- {
- System.out.println(map.get(iterator.next()));
- map.put("test5", "test555");
- }
-
- }
-
- }
- -----运行以上代码,将输出以下信息-----
- Exception in thread "main" java.util.ConcurrentModificationException
- at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
- at java.util.HashMap$KeyIterator.next(Unknown Source)
- at FailFastExample.main(FailFastExample.java:20)
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.Iterator;
- public class FailSafeExample
- {
- public static void main(String[] args)
- {
- ConcurrentHashMap<String,String> map =
- new ConcurrentHashMap<String,String>();
- map.put("test", "test");
- map.put("test2", "test2");
- map.put("test3","test3");
-
- Iterator iterator = map.keySet().iterator();
-
- while (iterator.hasNext())
- {
- System.out.println(map.get(iterator.next()));
- map.put("test5", "test5555");
- }
-
- }
-
- }
- 输出
- test
- test2
- test3
复制代码 fail-fast和fail-safe的区别
| Fail Fast Iterator | Fail Safe Iterator | Throw ConcurrentModification Exception | yes | no | Clone object | no | yes | Memory Overhead | no | yes | 例 | HashMap,Vector,ArrayList,HashSet | CopyOnWriteArrayList, ConcurrentHashMap |
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |