Java5 多线程(九)--jdk1.5同步集合


在JDK1.5之前没有推出同步集合的时候,可以通过Conllections集合工具类的synchronized+集合名称如:synchronizedSet(Set),现在不需要这种方式了使用 ConcurrentHashMap, ConcurrentSkipListMap, ConcurrentSkipListSet,ConcurrentLinkedQueue等这些集合即可.
1>线程不安全的集合出现的问题,死循环.
Race Condition(也叫做资源竞争),是多线程编程中比较头疼的问题特别是Java多线程当中,
经常会因为多线程同时访问相同的共享数据,而造成数据的不一致性,为了解决这个问题
通常来说需要加上同步标识synchronized,来保证数据串行的访问,但是synchronized是个性能杀手,
过多的使用会导致性能下降,特别是扩展性下降,使得系统不能使用多个CPU资源,这是性能测试当中
经常遇到的问题.
然而有一个公司的ERP系统出现了问题,然后就叫Java的高级工程师来解决,该工程师通发现当500个并发用访问的时候,居然把所有的CPU都压得满满的,通过过DTrace for Java工具发现很多CPU都在做同一件事,
那就是不停的执行一条语句(HashMap.get()方法).这是为什么呢?
我们知道遍历Map集合的时候,是这样的情形(下面只是伪代码):
while(hasNext()){
//每当循环一次cursor加1
//假设该集合里面有4个元素(count=4),如果循环到最后一次了cursor=4,就在此时另一个线程
//跑来把集合里面的一个元素给删除了(remove()),这时候count=3了,这时候上一个线程接着执行
//它会去判断hasNext(),但是count!=cursor了,而本来是相等的.这样就是死循环了.
}
hasNext(){
if(cursor==count){
return false;//不需要再循环了
}
return true;
}
总结: 线程不安全的集合,如果多个线程同时对其进行添加和删除操作, 有可能会出现致命的错误.

2>HashSet和HashMap关系
通过查看HashSet源码:
publicHashSet() {
map=newHashMap<E,Object>();
}发现HashSet实际上就是通过HashMap来实现的,不过它只用到了HashMap的key
3>线程不安全集合还有另一个隐患
public static void main(String[] args) {
//Collection users = new CopyOnWriteArrayList();
Collection users = new ArrayList();
users.add(new User("张三",28));
users.add(new User("李四",25));
users.add(new User("王五",31));
Iterator itrUsers = users.iterator();
while(itrUsers.hasNext()){
System.out.println("aaaa");
User user = (User)itrUsers.next();
if("张三".equals(user.getName())){
users.remove(user);
} else {
System.out.println(user);
}
}
}
运行程序发现出现异常:


这是为什么?
跟进AbstractList 343行:



分析如下:
我们来看一下这个
while(itrUsers.hasNext()){
User user = (User)itrUsers.next();
if("张三".equals(user.getName())){
users.remove(user);
} else {
System.out.println(user);
}
}
查看hasNext源码:

如果把 if("张三".equals(user.getName()))改成 if("王五".equals(user.getName()))
输出结果如下:

出现了第一次出现的异常,分析如下:
当第一循环执行到next()时候expectedModCount=3 modCount=3 cursor=1,size()=3
当第二循环执行到next()时候expectedModCount=3 modCount=3 cursor=2,size()=3
当第三循环执行到next()时候expectedModCount=3 modCount=4 cursor=3,size()=2
发现cursor任然不等于size(),循环人仍在继续,最后发现expectedModCount!=modCount抛出异常.所以控制太输出这样的结果.
要想迭代的时候同时操作集合可以使用JDK1.5提供的线程安全的集合,
只需要把集合改成如下即可:Collection users = new CopyOnWriteArrayList();


转载请注明出处 : http://blog.csdn.net/johnny901114/article/details/8696032




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值