当前位置: 首页 > 编程笔记 >

java 中modCount 详解及源码分析

子车海
2023-03-14
本文向大家介绍java 中modCount 详解及源码分析,包括了java 中modCount 详解及源码分析的使用技巧和注意事项,需要的朋友参考一下

modCount到底是干什么的呢

在ArrayList,LinkedList,HashMap等等的内部实现增,删,改中我们总能看到modCount的身影,modCount字面意思就是修改次数,但为什么要记录modCount的修改次数呢?

大家发现一个公共特点没有,所有使用modCount属性的全是线程不安全的,这是为什么呢?说明这个玩意肯定和线程安全有关系喽,那有什么关系呢

阅读源码,发现这玩意只有在本数据结构对应迭代器中才使用,以HashMap为例:

private abstract class HashIterator<E> implements Iterator<E> {
    Entry<K,V> next;    // next entry to return
    int expectedModCount;  // For fast-fail
    int index;       // current slot
    Entry<K,V> current;   // current entry

    HashIterator() {
      expectedModCount = modCount;
      if (size > 0) { // advance to first entry
        Entry[] t = table;
        while (index < t.length && (next = t[index++]) == null)
          ;
      }
    }

    public final boolean hasNext() {
      return next != null;
    }

    final Entry<K,V> nextEntry() {
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
      Entry<K,V> e = next;
      if (e == null)
        throw new NoSuchElementException();

      if ((next = e.next) == null) {
        Entry[] t = table;
        while (index < t.length && (next = t[index++]) == null)
          ;
      }
      current = e;
      return e;
    }

    public void remove() {
      if (current == null)
        throw new IllegalStateException();
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
      Object k = current.key;
      current = null;
      HashMap.this.removeEntryForKey(k);
      expectedModCount = modCount;
    }
  }

由以上代码可以看出,在一个迭代器初始的时候会赋予它调用这个迭代器的对象的mCount,如何在迭代器遍历的过程中,一旦发现这个对象的mcount和迭代器中存储的mcount不一样那就抛异常

好的,下面是这个的完整解释

Fail-Fast 机制

我们知道 java.util.HashMap 不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了map,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。这一策略在源码中的实现是通过 modCount 域,modCount 顾名思义就是修改次数,对HashMap 内容的修改都将增加这个值,那么在迭代器初始化过程中会将这个值赋给迭代器的 expectedModCount。在迭代过程中,判断 modCount 跟 expectedModCount 是否相等,如果不相等就表示已经有其他线程修改了 Map:注意到 modCount 声明为 volatile,保证线程之间修改的可见性。

所以在这里和大家建议,当大家遍历那些非线程安全的数据结构时,尽量使用迭代器

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

 类似资料:
  • 本文向大家介绍java 源码分析Arrays.asList方法详解,包括了java 源码分析Arrays.asList方法详解的使用技巧和注意事项,需要的朋友参考一下 最近,抽空把java Arrays 工具类的asList 方法做了源码分析,在网上整理了相关资料,记录下来,希望也能帮助读者! Arrays工具类提供了一个方法asList, 使用该方法可以将一个变长参数或者数组转换成List 。

  • 本文向大家介绍java TreeMap源码解析详解,包括了java TreeMap源码解析详解的使用技巧和注意事项,需要的朋友参考一下 java TreeMap源码解析详解  在介绍TreeMap之前,我们来了解一种数据结构:排序二叉树。相信学过数据结构的同学知道,这种结构的数据存储形式在查找的时候效率非常高。 如图所示,这种数据结构是以二叉树为基础的,所有的左孩子的value值都是小于根结点的v

  • 本文向大家介绍JAVA 枚举单例模式及源码分析的实例详解,包括了JAVA 枚举单例模式及源码分析的实例详解的使用技巧和注意事项,需要的朋友参考一下 JAVA 枚举单例模式及源码分析的实例详解       单例模式的实现有很多种,网上也分析了如今实现单利模式最好用枚举,好处不外乎三点: 1.线程安全 2.不会因为序列化而产生新实例 3.防止反射攻击但是貌似没有一篇文章解释ENUM单例如何实现了上述三

  • 问题内容: 在Eclipse中,我看到对象有一个字段。目的是什么?(修改数量?) 问题答案: 它允许列表的内部知道是否进行了结构修改,从而可能导致当前操作给出错误的结果。 如果您由于在迭代过程中修改列表(例如删除项目)而感到困惑,那么它的内部就是迭代器。 该AbstractList的文档提供一个良好的详细说明。

  • 本文向大家介绍Vue中之nextTick函数源码分析详解,包括了Vue中之nextTick函数源码分析详解的使用技巧和注意事项,需要的朋友参考一下 1. 什么是Vue.nextTick()? 官方文档解释如下: 在下次DOM更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。 2. 为什么要使用nextTick? 如上代码 在页面视图上显示bb,但是当我在控制台打印

  • 本文向大家介绍Java 中的注解详解及示例代码,包括了Java 中的注解详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 在Java中,注解(Annotation)引入始于Java5,用来描述Java代码的元信息,通常情况下注解不会直接影响代码的执行,尽管有些注解可以用来做到影响代码执行。 注解可以做什么 Java中的注解通常扮演以下角色 编译器指令 构建时指令 运行时指令 其中 Java内