1.快速失败(fail-fast)和安全失败(fail-safe)?

一:快速失败(fail—fast)

在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。

原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

注意:这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。

场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。

二:安全失败(fail—safe)

采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。

缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

2.线程安全的java集合,以及其原理 (https://www.imooc.com/article/34600)

jdk1.5之前实现集合的并发开发和jdk1.5版本以后有所差别

jdk1.5前:

  (1)最为简单直接的就是在程序中我们自己对共享变量进行加锁。不过,缺点也显而易见,手动实现线程安全间接增加了程序的复杂度,以及代码出错的概率---例如:线程死锁的产生;
  (2)我们还可以使用Java集合框架中的Vector、Hashtable实现类,这两个类都是线程安全的。不过,Java已不提倡使用。
  (3)此外,我们还可以使用集合工具类--Collections,通过调用其中的静态方法,来得到线程安全的集合。具体方法,包括:Collections.synchronizedCollection(Collection<T> c)、  Collections.synchronizedSet(Set<T> s)、Collections.synchronizedList(List<T>)、Collections.synchronizedMap(Map<K, V>)。
  究其原理,他们都是通过在方法中加synchronized同步锁来实现的。我们知道synchronized锁的开销较大,在程序中不建议使用。
  虽然,这三种方式可以实现线程安全的集合,但是都有显而易见的缺点,而且也不是我们今天所关注的重点。

jdk1.5推出了java.util.concurrent包。该包的出现,让Java并发编程变得更加轻松,帮助开发者编写更加高效、易维护、结构清晰的程序:

  阻塞式集合:当集合已满或为空时,被调用的添加(满)、移除(空)方法就不能立即被执行,调用这个方法的线程将被阻塞,一直等到该方法可以被成功执行。
  非阻塞式集合:当集合已满或为空时,被调用的添加(满)、移除(空)方法就不能立即被执行,调用这个方法的线程不会被阻塞,而是直接则返回null或抛出异常。

下面,就来看下concurrent包下,到底存在了哪些线程安全的集合:
Collection集合:

List:
  CopyOnWriteArrayList
Set:
  CopyOnWriteArraySet
  ConcurrentSkipListSet
Queue:
  BlockingQueue:
  LinkedBlockingQueue
DelayQueue
  PriorityBlockingQueue
  ConcurrentLinkedQueue
TransferQueue:
  LinkedTransferQueue
  BlockingDeque:
  LinkedBlockingDeque
  ConcurrentLinkedDeque
Map集合:

Map:
  ConcurrentMap:
  ConcurrentHashMap
  ConcurrentSkipListMap
  ConcurrentNavigableMap
通过以上可以看出,java.util.concurrent包为每一类集合都提供了线程安全的实现。

其中list又采用的是CopyOnWrite机制,我对其理解是,这个机制与Array不同的是,其在get()方法中是不加锁的,提升了性能.可以这么做的原因是,CopyOnWrite在add()的时候,既添加了锁,又拷贝了备份,在备份上操作后又将指针指回原地址.

简单的理解,就是当我们往CopyOnWrite容器中添加元素时,不直接操作当前容器,而是先将容器进行Copy,然后对Copy出的新容器进行修改,修改后,再将原容器的引用指向新的容器,即完成了整个修改操作;

更详细的解析需要到原博文去阅读

转载于:https://www.cnblogs.com/garfieldcgf/p/10283176.html

java集合 线程安全相关推荐

  1. java集合线程安全解决方案(List,Set,Map)

    一丶AarraList : 在多线程下多个线程操作ArrayList, 往里面放入数据或者删除数据输出数据会造成线程不安全. 对于ArrayList解决方案有三种: 1. 使用古老的Vector,Ve ...

  2. JAVA集合-线程安全

    一.其他的集合类 我们这里来介绍一点其他的集合类 1.1.Linkedhashmap Linkedhashmap在原来的基础上维护了一个双向链表,用来维护,插入的顺序. public class Li ...

  3. 【Java 集合】Java 集合的线程安全性 ( 加锁同步 | java.utils 集合 | 集合属性 | java.util.concurrent 集合 | CopyOnWrite 机制 )

    文章目录 I . Java 集合的线程安全概念 ( 加锁同步 ) II . 线程不安全集合 ( 没有并发需求 推荐使用 ) III . 集合属性说明 IV . 早期的线程安全集合 ( 不推荐使用 ) ...

  4. Java集合(实现类线程安全性)

    转载自  Java集合(实现类线程安全性) 1.集合和Map 下图是Java集合的Collection集合体系的继承树: 下图是Java的Map体系的继承树: 对于Set.List.Queue和Map ...

  5. 【重难点】【Java集合 02】Set、List、Map 的区别、常见的线程安全的集合类、Collection 为什么只能在 Iterator 中删除元素

    [重难点][Java集合 02]List.Set.Map 的区别.常见的线程安全的集合类.Collection 为什么只能在 Iterator 中删除元素 文章目录 [重难点][Java集合 02]L ...

  6. 面试宝典Java篇(基础+高级+集合+线程+IO+JVM)

    一.Java篇 1.1 Java基础篇 1.请你讲讲&和&&的区别? &运算符有两种用法:(1)按位与:(2)逻辑与. &&运算符是短路与运算. 逻辑与 ...

  7. Java 集合框架分析:线程安全的集合

    相关文章: Java 集合框架分析:Set http://blog.csdn.net/youyou1543724847/article/details/52733723 Java 集合框架分析:Lin ...

  8. java中线程安全的集合_Java中哪些集合类是线程安全的?

    线程安全类是确保类的内部状态以及从方法返回的值在从多个线程并发调用时是正确的类. Java中线程安全的集合类有Stack.Vector.Properties.Hashtable等. 堆栈(stack) ...

  9. java 集合 接口_Java集合之Collection接口

    1 - Java集合介绍 /* 1. 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象 的操作,就要对对象进行存储. 2. 另一方面,使用Array存储对象方面具有一些弊 端,而 ...

最新文章

  1. python收集网页中的翻页
  2. 有关session的登录注销的一个小例子
  3. zend framework1.11使用原生代码获取结果
  4. python刷取CSDN博文访问量之一
  5. 下取整函数的含义_Excel将3.14159取值为3.15或3.1415? 两个函数为你效劳,拿走不谢...
  6. CF1479B Painting the Array
  7. 基于三维激光点云的目标识别与跟踪研究
  8. Android中插件开发篇之----类加载器
  9. fullcalendar 上下月翻动事件_用期权做事件套利的黄金法则
  10. 转:多线程--六种多线程方法解决UI线程阻塞
  11. Docker客户端与守护进程
  12. CentOS6.7 i686上安装JDK7
  13. Epicor系统二次开发
  14. 考研复试(控制工程专硕)及大学本科(物联网工程)知识点回顾(三)——模拟电子技术
  15. 调用DialogFragment做进度条报java.lang.IllegalStateException: Fragment already added问题的最终解决方案
  16. 数据防泄密·工控安全保障方案
  17. Ps使用旋转扭曲制作图片
  18. 深入浅出XDL(一):Blaze推理引擎
  19. Thinkphp实战教程后台管理系统开发
  20. win7计算机没有光驱图标不见了,win7系统光驱图标消失怎么办

热门文章

  1. python刷今日头条阅读量_教你如何提高今日头条号推荐量阅读量播放量
  2. python 程序块 挂掉的服务_写一个python的服务监控程序
  3. springboot16 整合MyBatis
  4. spring学习--AOP术语
  5. win10安装Visual Studio Code(VSCode)
  6. mybatis 不生效 参数_Spring Boot(七):你不能不知道的Mybatis缓存机制
  7. php 405,php Restler 405 Method Not Allowed 问题解决啦,restlerallowed_PHP教程
  8. linux mysql 5.7.13 安装_mysql 5.7.13 安装配置方法图文教程(linux)
  9. python phpstudy_phpStudy后门分析及复现
  10. vc 2008建立c语言,C语言纯外行,要运行别人给的一个代码,用VC2008