java并发修改异常详解

并发修改异常

示例

package com.ningxiao.day18;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo02 {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();

        list.add("python");
        list.add("java");
        list.add("C");
        list.add("C++");

        Iterator<String> it = list.iterator();


        while (it.hasNext()){
            if (it.next().equals("python")){
                list.add(".net");
            }
        }
    }
}

Exception in thread "main"java.util.ConcurrentModificationException
at java.util.ArrayList$ Itr.checkForComodification(ArrayList.java:901)
atjava.util.ArrayList$Itr.next(ArrayList.java:851)atcom.ningxiao.day18.Demo02.main(Demo02.java:21)

分析

过程:
     从创建iterator迭代器开始分析:
         Iterator<String> it = list.iterator();
         现在我们去看底层源码:
              public Iterator<E> iterator() {
                 return new ArrayList.Itr();
             }
             根据ArrayList内部类Itr创建了一个对象并返回
             那我们去看一下这个内部类都有什么内容
                     private class Itr implements Iterator<E> {
                         ....
                         int expectedModCount;

                         Itr() {
                             this.expectedModCount = ArrayList.this.modCount;
                         }
                     }
                     我们发现他的无参构造方法初始化了一个属性
                         this.expectedModCount = ArrayList.this.modCount;
                     那么问题来了,这两个属性是什么?
                         expectedModCount 是期望修改值
                         this.modCount  是实际修改值
                         这两个是什么不重要,重要的是我们知道modCount初始值为0

     以上内容说明:
         在我们创建一个迭代器的时候,底层源码根据ArrayList内部类Itr帮我们创建了一个迭代器,并且这个迭代器的期望修改值和实际修改值一样

         那为什么会报错?
         我们看一下抛出的错误源码
         final void checkForComodification() {
             if (ArrayList.this.modCount != this.expectedModCount) {
                 throw new ConcurrentModificationException();
             }
         }
         源码说明,当期望修改值与实际修改值不一样的时候报错,
         但是在生成迭代器的时候明明两者是相同的,怎么就不一样了?
         到底是什么造成了这个错误?

         public boolean hasNext() {
             return this.cursor != ArrayList.this.size;
         }

         public E next() {
             this.checkForComodification();
             int i = this.cursor;
             if (i >= ArrayList.this.size) {
                 throw new NoSuchElementException();
             } else {
                 Object[] elementData = ArrayList.this.elementData;
                 if (i >= elementData.length) {
                     throw new ConcurrentModificationException();
                 } else {
                     this.cursor = i + 1;
                     return elementData[this.lastRet = i];
                 }
             }
         }
         这两个方法好像也没有修改那两个值
         public boolean add(E e) {
             ++this.modCount;
             this.add(e, this.elementData, this.size);
             return true;
         }
         add()方法修改了modCount值,原因就在这里,modCount改变
         而expectedModCount没有发生变化,就造成了两者不一样,因此
         在代码执行next()的时候
         public E next() {
             this.checkForComodification();
             int i = this.cursor;
             if (i >= ArrayList.this.size) {
                 throw new NoSuchElementException();
             } else {
                 Object[] elementData = ArrayList.this.elementData;
                 if (i >= elementData.length) {
                     throw new ConcurrentModificationException();
                 } else {
                     this.cursor = i + 1;
                     return elementData[this.lastRet = i];
                 }
             }
         }
         第一行就检查两者是否相等,因为两者不相等,就抛出了异常

解决的方案

​ 不使用迭代器,用for循环遍历,然后用集合对象做对应的操作即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值