传统容器的迭代器的并发问题
一个HashMap的案例:造成死循环
下面是HashMap的get方法的代码:
public V get(Object key){
if(key == null) return getForNullKey();
int hash = hash(key.hashCode());
for(Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next()){
Object k;
if(e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
原因:get方法会根据key的hashCode来锁定多个对象,并且遍历这些对象来找到key所对应的对象。当多个线程不安全的修改HashMap数据结构的时候,有可能使得这个方法进入死循环。
死循环举例:
count = 4;
while(hasnext()){next();} A
next(){cursor++;}
hasnext(){
if(cursor == count) return false; B
return ture;
}
线程TA:在A处执行4次next()完成的那刹那,TA阻塞,此时,cursor=4
线程TB:在A处执行next(),使得cursor=5,可见,永远不会出现B处cursor == count的情况。因此,程序进入死循环。
历史教训:在并发环境下,应当使用ConcurrentHashMap等并发库。注意,在并发环境下使用传统容器并对它进行修改,会出现异想不到的异常或错误。
|
|