本帖最后由 杨_扬 于 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比较这两个值,发现不等,抛异常。基本原理就是这样。
|