我是靠谱客的博主 贪玩小白菜,最近开发中收集的这篇文章主要介绍【Java 并发】浅析同步容器类与并发容器类【Java 并发】浅析同步容器类与并发容器类,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

【Java 并发】浅析同步容器类与并发容器类

一,同步容器类
最简单直接的理解:同步容器类就是将方法通过synchronized修饰达到线程安全的类。这些类实现线程安全的方式是:将状态封装起来,并对每个方法进行同步,使得即使在多线程,每一次也仅有一个线程可以访问容器的状态。结果变成了类似于串行执行的效果。仅仅只为实现同步。

常见的同步容器类
1,Vector(implements List),Hashtable(implements Map),Stack(extends Vector)。
2,Collections.synchronizedXxxx。

Vector中的部分方法
这里写图片描述

存在的问题
1,同步容器在单线程的环境下能够保证线程安全,但是通过synchronized同步方法将访问操作串行化,导致并发环境下效率低下。而且同步容器在多线程环境下的复合操作(迭代、条件运算如没有则添加等)是非线程安全,需要客户端代码来实现加锁。

public static Object getLast(Vector list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
public static void deleteLast(Vector list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}

在多线程的情况,一个线程在调用getLast,同时另一个线程在调用deleteLast将元素删除,此时getLast将抛出越界异常。
可以在客户端通过获取容器类的锁,使得两个操作成为原子操作。虽然可以避免之前的问题,但是这也降低了并发的效率,而仅仅实现了同步。

public static Object getLast(Vector list) {
synchronized(list){
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
}
public static void deleteLast(Vector list) {
synchronized(list){
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
}

2,迭代器与ConcurrentModificationException异常
因为“fail-fast”,当容器在迭代过程中被修改了,就会抛出ConcurrentModificationException异常。这种机制并不是一种完备机制,而只是告诉你并发错误。文档中也写到:it would be wrong to write a program that depended on thisexception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
解决办法就是整个迭代过程持有容器的锁,但是这这又很大程度降低并发效率。迭代规模很大时,就是有很多线程被阻塞等待锁。

二,并发容器类
同步容器类的存在的问题,使之成为鸡肋,食之无味,弃之可惜。于是就有了并发容器类来改进性能。
关于并发容器类的介绍,http://blog.csdn.net/u011080472/article/details/51418850#reply 中有详细介绍

1,锁分段
Hashtable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下Hashtable的效率非常低下。因为当一个线程访问Hashtable的同步方法时,其他线程访问Hashtable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。
Hashtable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问Hashtable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,

在ConcurrentHashMap中使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。假设使用合理的散列算法使关键字能够均匀的分部,那么这大约能使对锁的请求减少到越来的1/16。也正是这项技术使得ConcurrentHashMap支持多达16个并发的写入线程。

锁分段的劣势在于:当一个线程需要获得多个锁实现独占访问时将会更加困难,并且开销更大。比如要扩大ConcurrentHashMap容器,以及重新计算键值的散列值。

以上都是阅读《Java编程思想》-并发和《Java并发编程实践》的笔记,不喜勿喷!

最后

以上就是贪玩小白菜为你收集整理的【Java 并发】浅析同步容器类与并发容器类【Java 并发】浅析同步容器类与并发容器类的全部内容,希望文章能够帮你解决【Java 并发】浅析同步容器类与并发容器类【Java 并发】浅析同步容器类与并发容器类所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部