java集合 线程安全
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出的新容器进行修改,修改后,再将原容器的引用指向新的容器,即完成了整个修改操作;
更详细的解析需要到原博文去阅读
java集合 线程安全的更多相关文章
- Java集合--线程安全(CopyOnWrite机制)
5 Java并发集合 5.1 引言 在前几章中,我们介绍了Java集合的内容,具体包括ArrayList.HashSet.HashMap.ArrayQueue等实现类. 不知道各位有没有发现,上述集合 ...
- Java 集合 线程安全
Java中常用的集合框架中的实现类HashSet.TreeSet.ArrayList.ArrayDeque.LinkedList.HashMap.TreeMap都是线程不安全的,如果多个线程同时访问它 ...
- java集合线程安全测试
package com.cxy; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import ...
- java利用线程池处理集合
java利用线程池处理集合 2018年07月23日 17:21:19 衍夏成歌 阅读数:866 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/s ...
- 08 Java 集合的线程安全问题
1 Java中的集合 Java中的集合分为同步的集合(线程安全)和线程不安全的集合 例如 : ArrayList和Vector的区别: 一.同步性:Vector是线程安全的,也就是说是同步的,而Arr ...
- java面试| 线程面试题集合
集合的面试题就不罗列了,基本上在深入理解集合系列已覆盖 「 深入浅出 」java集合Collection和Map 「 深入浅出 」集合List 「 深入浅出 」集合Set 这里搜罗网上常用线程面试题, ...
- java 集合及其线程安全 及其 set linkedList map table 区别
早在jdk的1.1版本中,所有的集合都是线程安全的.但是在1.2以及之后的版本中就出现了一些线程不安全的集合,为什么版本升级会出现一些线程不安全的集合呢?因为线程不安全的集合普遍比线程安全的集合效率高 ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- java集合你了解多少?
用了java集合这么久,还没有系统的研究过java的集合结构,今天亲自画了下类图,总算有所收获. 一.所有集合都实现了Iterable接口. Iterable接口中包含一个抽象方法:Iterator& ...
随机推荐
- BZOJ.3504.[CQOI2014]危桥(最大流ISAP)
BZOJ 洛谷 这种题大多是多源多汇跑网络流.往返\(a_n/b_n\)次可以看做去\(a_n/b_n\)次,直接把危桥能走的次数看做\(1\). 先不考虑别的,直接按原图建模:危桥建双向边容量为\( ...
- Kotlin基础(五)Kotlin的类型系统
Kotlin的类型系统 一.可空类型 //s为null的话编译器会报错,没问号不能为空 fun strLen(s : String)=s.length //如果允许s为空可: fun strLen2( ...
- Scrapy基础(三) ------xpath基础
xpath简介 1,使用路径表达式在xml和html中解析 2,包含标准函数路(所有库支持的xpath语法一致) 3,W3C标准 节点: <body> 第一个节点: <h ...
- Tensorflow显示图片
Tensorflow在处理数据时,经常加载图像数据,有的时候是直接读取文件,有的则是读取二进制文件,为了更好的理解Tensorflow数据处理模式,先简单讲解显示图片机制,就能更好掌握是否读取正确了. ...
- Module not found: Error: Can't resolve 'XXX' in 'XXXX'
故障 控制台运行webpack/npm时出现 Module not found: Error: Can't resolve 'XXX' in 'XXXX' 解决方案 npm i XXX --save ...
- 通过 curl 传递数据
方法一(若为post方式,只适用于一维数组) /** * curl发送htpp请求 * 可以发送https,http,get方式,post方式,post数据发送 */ public function ...
- javascript对属性的操作
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- GMA Round 1 函数求值
传送门 函数求值 设函数$f(x)=x^{2018}+a_{2017}*x^{2017}+a_{2016}*x^{2016}+...+a_{2}*x^2+a_{1}*x+a_{0}$,其中$a_{0} ...
- SpringMVC知识点
一.SpringMVC 1.HelloWorld案例 ①步骤: 加jar包 在web.xml文件中配置DispatcherServlet 加入SpringMVC的配置文件 编写处理请求的处理器,并标识 ...
- vue路由打开新窗口
一. <router-link>标签实现新窗口打开: 官方文档中说 v-link 指令被 <router-link> 组件指令替代,且 <router-link> ...