Java多线程——同步容器类
1、同步容器类
同步容器类包括Vector和Hashtable,是早期JDK的一部分,这些类实现的方法是:将它们的状态封装起来,并对每个共有的方法进行同步,使得每个线程只有一个线程能访问它们。
1.1 、同步容器类问题
同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作。复合类操作如:迭代(反复访问元素,遍历完容器中的所有元素)、跳转(根据指定的顺序找到当前元素的下一个元素)、以及条件运算。这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为。如下面的代码:
for(int i = 0; i < vector.size(); i++){
doSomething(vector.get(i));
}
单线程中,这是成立的,但是在多线程中,有其他的线程并发的修改vector,则可能会导致麻烦,假如在对vector进行迭代时,另一个线程删除了一个元素,则可能会抛出ArrayIndexOutOfBoundsException异常。但是我们可以通过客户端加锁的机制来解决该问题,如下:
synchronized (vector) {
for(int i = 0; i < vector.size(); i++){
doSomething(vector.get(i));
}
}
1.2 迭代器与ConcurrentModificationException
当容器在迭代过程中被修改,就会抛出ConcurrentModificationException异常。如果想在迭代过程中,不被其他线程修改容器,还得加锁,或者克隆一个副本出来,在副本上进行迭代,这样就避免了抛出ConcurrentModificationException异常。
1.2 隐藏迭代器
虽然加锁可以防止迭代器抛出ConcurrentModificationException异常,但你必须要记住在所有的对所有共享容器进行迭代的地方都需要加锁。因为在某些情况下,迭代器有隐藏起来,比如我们在输出一个容器的时候,会间接的调用toString()方法,标准容器的toString方法将对容器进行迭代。容器的hashCode,equals,containsAll等方法,都会对容器进行迭代,这些间接的迭代都可能会抛出ConcurrentModificationException异常。
2、并发容器
同步容器将所有对容器状态的访问都串行化来实现它们的安全性。这中方法的代价是严重降低并发性,当多个容器竞争容器的锁时,吞吐量将严重降低。并发容器是针对多个线程并发访问设计的,通过并发容器代替同步容器,可以极大的提高伸缩性并降低风险。
java5.0之后提供了多种并发容器来改善同步容器的性能,如ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentSkipListMap等;我们对它们进行详细介绍。
2.1 ConcurrentHashMap
ConcurrentHashMap并不是将每个方法都在同一个锁上同步并使得每次只能一个线程访问容器,而是使用一种粒度更细的加锁机制来实现更大程度的共享,这种机制被称为分段锁(Lock Striping),这种加锁机制带来的结果是,在并发访问的环境下将实现更高的吞吐量,在单线程上只损失非常小的性能。
这篇文章详细的介绍了ConcurrentHashMap的原理:http://www.cnblogs.com/ITtangtang/p/3948786.html。
2.2 CopyOnWriteArrayList
CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。详细的介绍看这里:http://www.cnblogs.com/dolphin0520/p/3938914.html
Java多线程——同步容器类的更多相关文章
- Java多线程同步问题的探究
一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...
- 转:关于JAVA多线程同步
转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖 ...
- java多线程同步
一篇好文:java多线程机制同步原则 概括起来说,Java 多线程同步机制主要包含如下几点:1:如果一个类包含一个或几个同步方法,那么由此类生成的每一个对象都配备一个队列用来容纳那些等待执行同步的线程 ...
- Java多线程-同步:synchronized 和线程通信:生产者消费者模式
大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...
- 转:java多线程--同步容器
java同步容器 在Java的集合容器框架中,主要有四大类别:List.Set.Queue.Map.List.Set.Queue接口分别继承了Collection接口,Map本身是一个接口.注意Col ...
- Java多线程同步 synchronized 关键字的使用
代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A, ...
- Java多线程---同步与锁
一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动 ...
- Java多线程同步的方法
一 synchronized关键字 1.synchronized实现原理: ---基于对象监视器(锁) java中所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数 ...
- Java 多线程同步的五种方法
一.引言 闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子 ...
随机推荐
- QEMU 代码分析:BIOS 的加载过程
http://www.ibm.com/developerworks/cn/linux/1410_qiaoly_qemubios/ QEMU 中使用 BIOS 简介 BIOS 提供主板或者显卡的固件信息 ...
- iconv-go升级过程中的编译问题
工作项目原因,需要对golang进行升级.升级之后老的iconv-go运行有问题.因为新的golang运行更加严格,所以需要升级iconv-go. 从djimenez/iconv-go 拉下来代码进行 ...
- CentOS7防火墙firewall相关操作
1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl disabl ...
- Golang template和junit xml report转html工具
最近刚好有个task是要用Golang把Junit的XML格式report转换成HTML格式,便学习了Golang的template包. 基于template做的那个junit XML转HTML工具. ...
- 20172325 2018-2019-2 《Java程序设计》第三周学习总结
20172325 2018-2019-2 <Java程序设计>第三周学习总结 教材学习内容总结 一.什么是队列? 队列是一种线性集合,其元素从一端加入,从另一端删除: 队列的元素按照FIF ...
- Oracle GoldenGate 四、数据过滤和数据项匹配
写在开始前 从两周前我花了大量的业余时间阅读GoldenGate官方文档,并根据文档实践和进一步学习了解GoldenGate,以下便是根据官方文档理解总结的GoldenGate学习内容: Oracle ...
- 利用BeanUtils.copyProperties 克隆出新对象,避免对象重复问题
1.经常用jQuery获取标签里面值val(),或者html(),text()等等,有次想把获取标签的全部html元素包括自己也用来操作,查询了半天发现$("#lefttr1"). ...
- Hadoop学习【一】单机版搭建
首先要说一下,Hadoop 2.x版本以后的改动,在这里帖一篇文章,觉得写的不错. http://www.ibm.com/developerworks/cn/opensource/os-cn-hado ...
- 创建 Android 项目
创建 Android 项目 上一页下一页 您也应该阅读 项目概览 本课向您介绍如何使用 Android Studio 创建新的 Android 项目并介绍该项目中的一些文件. 在 Android St ...
- jmeter 计数器 (可自动生成新数字、注册专用)
1.打开jmeter,创建好线程组后,添加计数器 2.设置计数器 3.添加HTTP请求,验证所设置的计数器 4.填写对应参数 5.添加查看结果树,查看结果 6.修改一下线程属性 7.跑一下,看下结果就 ...