在我们详细讨论这两种机制的区别之前,首先得先了解并发修改。

1.什么是同步修改?

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

2.什么是 fail-fast 机制?

fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。

fail-fast会在以下两种情况下抛出ConcurrentModificationException

(1)单线程环境

集合被创建后,在遍历它的过程中修改了结构。

注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

(2)多线程环境

当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。

3. 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();
}
}

可以看到它的标记“mode”为 expectedModeCount

4. fail-safe机制

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

fail-safe机制有两个问题

(1)需要复制集合,产生大量的无效对象,开销大

(2)无法保证读取的数据是目前原始数据结构中的数据。

5 fail-fast 和 fail-safe的例子

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map; public class FailFastExample { public static void main(String[] args) {
Map<String, String> phone = new Hashtable<>();
phone.put("Apple", "iPhone");
phone.put("HTC", "HTC one");
phone.put("Samsung", "S5"); Iterator iterator = phone.keySet().iterator();
while (iterator.hasNext()) {
System.out.println(phone.get(iterator.next()));
phone.put("Huawei", "honor");
}
}
}

运行结果:

import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator; public class FailSafeExample {
public static void main(String[] args) {
ConcurrentHashMap<String, String> phone = new ConcurrentHashMap<>();
phone.put("Apple", "iPhone");
phone.put("HTC", "HTC one");
phone.put("Samsung", "S5"); Iterator iterator = phone.keySet().iterator(); while (iterator.hasNext()) {
System.out.println(phone.get(iterator.next()));
phone.put("Huawei", "honor");
}
}
}

6.fail-fast和 fail-safe 的区别

Fail Fast Iterator Fail Safe Iterator
Throw ConcurrentModification Exception Yes No
Clone object No Yes
Memory Overhead No Yes
Examples HashMap,Vector,ArrayList,HashSet,HashTable CopyOnWriteArrayList,ConcurrentHashMap

Java中的fail-fast和 fail-safe 的区别的更多相关文章

  1. Fail Fast and Fail Safe Iterators in Java

    https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/ Fail Fast and Fail Safe Iterators ...

  2. Java中集合List,Map和Set的区别

    Java中集合List,Map和Set的区别 1.List和Set的父接口是Collection,而Map不是 2.List中的元素是有序的,可以重复的 3.Map是Key-Value映射关系,且Ke ...

  3. Java中的“==操作符”和equals方法有什么区别

    Java中的"=="和equals方法究竟有什么区别? 1.==操作符 "=="操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的 ...

  4. java中,return和return null有什么区别吗?

    java中,return和return null有什么区别吗? 最大的区别:return;方法的返回值必须是void!return null;方法的返回值必须不是 原始数据类型(封装类除过)和void ...

  5. Java中关键字continue、break和return的区别

    Java中关键字continue.break和return的区别: continue:跳出本次循环继续下一次循环 break:   跳出循环体,继续执行循环外的函数体 return:   跳出整个函数 ...

  6. java中4种修饰符访问权限的区别及详解全过程

    java中4种修饰符访问权限的区别及详解全过程 http://jingyan.baidu.com/article/fedf0737700b3335ac8977ca.html java中4中修饰符分别为 ...

  7. Java中Compareable和Comparator两种比较器的区别

    Java中Compareable和Comparator两种比较器的区别 参考原文链接:https://www.cnblogs.com/ldy-blogs/p/8488138.html 1.引言 在ja ...

  8. java中的NIO和IO到底是什么区别?20个问题告诉你答案

    摘要:NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多. 本文分享自华为云社区<jav ...

  9. fail fast和fail safe策略

    优先考虑出现异常的场景,当程序出现异常的时候,直接抛出异常,随后程序终止 import java.util.ArrayList; import java.util.Collections; impor ...

  10. java中静态代理跟动态代理之间的区别

    文章转载于:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另 ...

随机推荐

  1. ping 路由跟踪

    pathping: pathping ip地址/网址 C:\Users\Administrator>pathping 119.29.18.11 通过最多 30 个跃点跟踪到 119.29.18. ...

  2. 风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧

    风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧 XSS绕过-过滤-编码 核心思想 后台过滤了特殊字符,比如说

  3. WPF 调试时拖拽不生效

    WPF窗体代码 <Window x:Class="SerialLabelDemo.Test.Window10" xmlns="http://schemas.micr ...

  4. PHP 自定义 alert 跳转方法

    /** * 跳转方法 * @param $msg * @param null $path * @param null $parent */ public function alert($msg,$pa ...

  5. Mac安装mysqlclient

    前言 祝大家身体健康 正文 如何在Mac上安装Python的mysqlclient模块 安装mysql brew install mysql 安装mysql-client brew install m ...

  6. 服务器报错"您的主机中的软件中止了一个已建立的连接"

    网上很多的说法都模棱两可,只是说和远程连接有关,这个说的太泛泛了. 我现在遇到的问题是java web出现的, 执行表单提交的时候出现该错误,原因是ajax和表单同时提交导致的, 相信很多朋友用了aj ...

  7. Java开发手册之安全规约

    1.用户敏感数据禁止直接展示,必须对展示数据进行脱敏.例如手机号.银行卡号等,中间要用*隐藏. 2.发贴.评论.发送即时消息等用户生成内容的场景必须实现防刷.文本内容违禁词过滤等风控策略,一般是用验证 ...

  8. 【Python】用字母生成图像

    用字母生成图像会用到matplotlib.pyplot库 所以需要安装这个库 pip install matplotlib 等待安装完成即可 ps:由于网络原因,会出现多次的timeout,可以使用国 ...

  9. 【Oracle】to_data() to_char()用法解析

    1.转换函数 与date操作关系最大的就是两个转换函数:to_date(),to_char()      to_date() 作用将字符类型按一定格式转化为日期类型:      具体用法:to_dat ...

  10. RWCTF2020 DBaaSadge 复现

    数据库题目 2020RWCTF DBaaSadge WP 这是一个很有意思的题目,难到让我绝望,跟着大佬smity的思路跑一下,求大佬抱抱. https://mp.weixin.qq.com/s/jv ...