A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 吴扬 中级黑马   /  2012-7-6 12:02  /  1941 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

毕老师在讲ListIterator这部分内容的时候,先是引出了一个异常,那就是ConcurrentModificationException异常,是因为对ArrayList集合中的元素即调用了List中的方法又调用了Iterator中的方法进行访问,这样才会抛出该异常。本人就觉得这种情况很像多线程中的并发访问异常,这个异常可以用解决多线程的同步锁的思想去解决吗?多线程可不可以用于解决非多线程而产生的异常呢?

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

2 个回复

倒序浏览
本帖最后由 杨_扬 于 2012-7-6 13:00 编辑

问的不错
首先,这的确是类似并发访问
老师用的啥例子我不知道,那部分视频我没看,我给出一个例子
ArrayList<String> list=new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
for(String s:list){
       System.out.println(m);
       list.add("dd");//look here ,problem point
}
你肯定知道,这段代码一执行,立马就跳ConcurrentModificationException了是吧?
用你说的同步锁的思想,解释一下
首先,有两个操作,一个是iterator在遍历集合,另一个操作是list在添加元素,我们将这两个操作视为两个线程。
这里,已经满足了线程同步的基本要素
1. 有两个或以上线程
2. 操作同一个资源(就是那个ArrayList)
假设,我们将List中的所有操作都包括在同步块中,那么当iterator拿到了执行权,只要遍历不结束,list就没办法add,反之亦然
这个同步锁的锁是谁呢?就是list.this对吧

那么,对于ArrayList来说,“锁”是谁呢?这就还要去看他的父类
AbstractList的源代码了。
AbstractList包含一个 modCount(modify count 修改次数)变量,它的初始值是0,当集合每被修改一次时(调用add,remove等方法),modCount加1。因此,modCount如果不 变,表示集合内容未被修改。
另外,还有一个叫
expectedModCount(expected modify count 预期修改次数)的变量
Itr是List用来实现Iteratorj接口的内部类,返回Iterator接口的实例,初始化时用expectedModCount记录集合的modCount变量,此后它会检测modCount的值
如果modCount与一开始记录在expectedModeCount中的值不等,说明集合内容被修改过,此时会抛出ConcurrentModificationException。
此时,
expectedModCount就相当于List集合的“锁”我们再回过头来分析一下程序
list.add("aa");
list.add("bb");
list.add("cc");
这三步执行完,对list做了三次修改,因此
modCount的值为3,而expectedModeCount的值也为3,接下来开始进入循环for(String s:list){
       System.out.println(m);
       list.add("dd");//look here ,problem point
}
当执行到add操作的时候
modCount的值变为了4,但是expectedModeCount的值依然为3
在进入下一次迭代之前,iterator比较这两个值,发现不等,抛异常。基本原理就是这样。

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
杨_扬 发表于 2012-7-6 12:36
问的不错
首先,这的确是类似并发访问
老师用的啥例子我不知道,那部分视频我没看,我给出一个例子

你这里用for循环进行遍历,而不是用迭代器进行遍历,这样就不会造成并发访问异常呀!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马