在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,保证线程之间修改的可见性。



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

转载地址:http://blog.csdn.net/u012926924/article/details/50452411

modCount到底是干什么的呢的更多相关文章

  1. 从TP-Link到雷蛇,纷纷入局智能手机业到底想干什么?

    ​   "眼看他起朱楼,眼看他宴宾客,眼看他楼塌了",这句形容世态炎凉的话其实与智能手机市场更为相像.诺基亚的辉煌与没落.黑莓的强势与消声无迹.摩托罗拉的数次易手.小米的横空出世与 ...

  2. 汽车AC键到底是干什么的?老司机告诉你

    现在很多人都会开车,想我当初学车的时候一会就可以上手了,开车简单,但是很多细节方面的就是得慢慢学习的过程,比如说汽车的AC键,我相信很多车主,包括老司机都不知道到底有哪些作用,只知道开空调,其实它的用 ...

  3. DNS到底是干什么用的

    DNS,DomainNameSystem或者DomainNameService(域名系统或者余名服务).域名系统为Internet上的主机分配域名地址和IP地址.用户使用域名地址,该系统就会自动把域名 ...

  4. 转自知乎大神----JS 的 new 到底是干什么的?

    大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不应该引入另一个更复杂的事物. 今天我从「省代码」的角度来讲 new. --------------------- ...

  5. linux 里rpm包到底是干什么用的

    Linux RPM全称是“RedHat Package Manager”,最早是Red Hat公司开发的,后来在CentOS.Fedora.SUSE都用它.而rpm包则是软件编译完成后按照RPM机制打 ...

  6. request中的那些方法到底是干什么的?

    最近做Java Web项目,在.jsp页面和servlet之间request和response还是有些混淆,查阅了一些资料,总结如下,方便以后使用: 首先,servlet接口是最基本的,提供的五个方法 ...

  7. tomcat到底是干什么用的?用大白话讲一下

    通俗点说他是jsp网站的服务器之一,就像asp网站要用到微软的IIS服务器,php网站用apache服务器一样,因为你的jsp动态网站使用脚本语言等写的,需要有服务器来解释你的语言吧,服务器就是这个功 ...

  8. webpack到底是干什么用的?

    转载于:https://segmentfault.com/a/1190000014148611?utm_source=tag-newest 概念问题一:什么是webpack和grunt和gulp有什么 ...

  9. js编程思想:模型进化论--JS 的 new 到底是干什么的?

    想象我们在制作一个策略类战争游戏,玩家可以操作一堆士兵攻击敌方. 我们着重来研究一下这个游戏里面的「制造士兵」环节. 一个士兵的在计算机里就是一堆属性,如下图: 一.荒蛮时代:对象是数据的集合 我们只 ...

随机推荐

  1. hibernate注解 笔记

    1.hibernate使用@where实现条件过滤功能 其里面只有一个参数clause,完整用法是: @Where(clause = "VALID_FLAG=1") 可以加在实体类 ...

  2. TX2--安装跑一python3.5

    sudo add-apt-repository ppa:webupd8team/javasudo apt-get updatesudo apt-get install oracle-java8-ins ...

  3. ios 进阶技术点

    1.Runtime的消息转发机制 消息转发机制基本上分为三个步骤: 1. 动态方法解析 2. 备用接收者 3. 完整转发 2.Runloop的工作原理 runloop.autorelease pool ...

  4. 在开发过程中遇到的Oracle的坑及开发技巧

    本人与2018年毕业,工作一年多,仍是菜鸟,自毕业以来一直从事java软件开发工作,工作中大部分数据库都是使用的Oracle,碰到的问题总结一下(随时更新). 1.sql中使用group by 分组时 ...

  5. docker搭建redis主从集群和sentinel哨兵集群,springboot客户端连接

    花了两天搭建redis主从集群和sentinel哨兵集群,讲一下springboot客户端连接测试情况 redis主从集群 从网上查看说是有两种方式:一种是指定配置文件,一种是不指定配置文件 引用地址 ...

  6. python数据拼接: pd.concat

    1.concat concat函数是在pandas底下的方法,可以将数据根据不同的轴作简单的融合 pd.concat(objs, axis=0, join='outer', join_axes=Non ...

  7. Sequence Models Week 2 Operations on word vectors

    Operations on word vectors Welcome to your first assignment of this week! Because word embeddings ar ...

  8. SpringCloud学习之Stream消息驱动【默认通道】(十)

    在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,而以往使用了中间件比如RabbitMQ,那么该中间件和系统的耦合性就会非常高,如果我们要替换为Kafka那么变动会比较大,这时我们可以使用S ...

  9. Python Learning Day1

    字符串的操作 # 字符串的操作 str1 = 'my name is xxx, my age is 18.' # 优先掌握的操作: # 1.按索引取值(正向取+反向取) :只能取 print(str1 ...

  10. 牛牛的DRB迷宫(DP、二进制编码器)

    牛牛的DRB迷宫I 链接:https://ac.nowcoder.com/acm/contest/3004/A来源:牛客网 题目描述 牛牛有一个n*m的迷宫,对于迷宫中的每个格子都为'R','D',' ...