美文网首页程序员
谈一谈ConcurrentModificationExcepti

谈一谈ConcurrentModificationExcepti

作者: jsbintask | 来源:发表于2019-04-09 22:53 被阅读0次
ConcurrentModificationException

本文原创地址,我的博客https://jsbintask.cn/2019/04/09/jdk/jdk8-concurrentmodificationexception/(食用效果最佳),转载请注明出处!

前言

ConCurrentModificationException是jdk用于限制并发情况下容器结构改变的异常类。当一个线程操作一个容器时,此时如果有另一个线程修改了容器大小,将抛出这个异常,我们看下面两段代码

ConcurrentModificationException
ConcurrentModificationException
Code 2::
ConcurrentModificationException
说明:一个线程进行list的排序操作,一个线程移除list中的元素,结果:
ConcurrentModificationException
上面代码说明不管是单线程情况下还是多线程并发运行模式下,一旦在某些情况下(如上面的遍历,排序),容器的结构一旦被修改就将抛出ConCurrentModificationException

源码解析

为什么会这样呢,这样是不是就代表这些容器是线程安全的呢? 我们通过源码来讨论一下。
首先第一个例子,一个线程进行遍历操作:for(T t: Collections),通过查看字节码知道,它其实就是使用了Iterator进行了遍历操作:

ConcurrentModificationException
接着查看ArrayList中的Iterator发现它内部是这么定义的:
ConcurrentModificationException
ArrayList内部有一个modCount成员变量,每次就行修改操作如增加,删除等会增加该值:
ConcurrentModificationException
而当初始化一个Iterator时,会记录当前的modCount,以后每次操作(next(), remove())都会检查该值:
ConcurrentModificationException
一旦和记录的初始值不相等,则会抛出异常!
同理,上面的排序操作sort()方法同样是这么定义的:
ConcurrentModificationException

这样我们上面的疑问就解开了,之所以会抛出异常,是因为容器内部维护了一个变量modCount,在进行某些操作时(iterator,sort)时,会记录当时的这个值,在操作过程中这个值一旦发生改变则会抛出ConcurrentModificationException。

jdk中,这种行为被称为快速失败,它的目的是为了尽最大努力的检测线程安全!但是! 它并不能保证容器的线程安全

ConcurrentModificationException
这个例子中,我们使用多线程添加了10000个元素,最后成功添加的却只有9993个元素,说明它内部并没有保证线程安全! 当我们在并发情况下使用这些容器时就需要考虑线程安全问题,替换线程安全的容器类(如ConcurrentHashMap, Vector, CopyOnWriteArrayList等)或者使用额外的同步手段如加锁!

扩展

在单线程遍历时,如果想删除某个元素,可以使用iterator.remove()

ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    list.add("list->" + (i + 1));
}

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String next = iterator.next();
    if (next.equals("list->3")) {
        iterator.remove();
    }

    System.out.println(next);
}
System.out.println(list);
ConcurrentModificationException
对于ArrayList而言,你也可以调用lsitIterator()方法获取内部的ListIterator从而进行添加,插入操作:
ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add("list->" + (i + 1));
        }

        ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            if (next.equals("list->3")) {
                iterator.remove();

            }

            System.out.println(next);
            iterator.add("list->7");
        }
        System.out.println(list);
ConcurrentModificationException
关注我,这里只有干货!

相关文章

  • 谈一谈ConcurrentModificationExcepti

    本文原创地址,我的博客:https://jsbintask.cn/2019/04/09/jdk/jdk8-conc...

  • 集合和ConcurrentModificationExcepti

    集合小练习,求每一个字符串出现的次数 遇到的小问题:ConcurrentModificationException

  • 记一次ConcurrentModificationExcepti

    java相关的工程师,对ConcurrentModificationException应该是很熟悉了。在并发中使用...

  • 2017-07-02

    好久没有坐下来好好谈一谈了 彼此带着接纳的态度 自然和气的谈一谈 谈一谈最近该说的话 该做的事 谈一谈大致以后的方...

  • 520----我喜欢暗恋着你的自己

    今天520,好像很适合谈一谈爱情,如果要谈一谈爱情,我最想和你谈一谈暗恋。 我为什么选择暗恋? 你还记得你是怎么发...

  • 《清明时》

    《清明时》 清明,城市应该是空旷的 人们散布于野地,与死人相守 谈一谈生活,谈一谈春天,谈一谈这么多年 这一天应该...

  • 我有笔好几亿的生意

    想和你谈一谈

  • 今天我想找个陌生人聊聊

    今天我想找个陌生人聊聊 不谈别的 就谈一谈爱情 谈一谈理想 谈一谈天地 还有干净的食物 新鲜的空气以及一点点骨气 ...

  • iOS-谈一谈自适应Cell的高度缓存

    iOS-谈一谈自适应Cell的高度缓存 iOS-谈一谈自适应Cell的高度缓存

  • 女神杂谈 20200508

    嗯,是一个宁静的夜晚。今晚主要谈谈个人感觉吧,谈一谈美女,谈谈女神,谈一谈张蓉蓉,谈一谈其他的,有可能是任神,也有...

网友评论

    本文标题:谈一谈ConcurrentModificationExcepti

    本文链接:https://www.haomeiwen.com/subject/pomwiqtx.html