//在ArrayList中
protected transient int modCount = 0;
//在HashMap中
transient int modCount;
//在LinkedList中
protected transient int modCount = 0;
上面的代码是在ArrayList、HashMap、LinkedList中找到的,属性名一样,定义方式类似。
transient
这个关键字主要就是让对象序列化时忽略modCount
我们来看看属性的说明
在结构上修改这个HashMap的次数,结构修改是指改变映射的数量HashMap或以其他方式修改其内部结构(例如重复)。此字段用于在集合视图上生成迭代器HashMap失败得很快。(见ConcurrentModificationException)。
有道翻译可能不太好理解,那我们直接上代码吧
代码copy于ArrayList中
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
final Object[] es = elementData;
final int size = this.size;
for (int i = 0; modCount == expectedModCount && i < size; i++)
action.accept(elementAt(es, i));
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
在ArrayList中我们可以看到
final int expectedModCount = modCount;
//.....//
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
然后后面进行if判断modCount != expectedModCount
,expectedModCount
的值是从modCount
来在这段代码中并未对两个变量进行修改,他们怎么会不相等呢?这里是不是属于代码冗余呢?
如果您也有这样的疑问的话。那么这篇博客你就看的值了。
如果是单线程中这的确是冗余的,但是一旦到了多线程中,其他线程对这个ArrayList的实例进行了一个add remove
等操作,改变了ArrayList数据结构。那么modCount
就改变了,同样modCount != expectedModCount
也就成立了,本次遍历有误,抛出异常
查看他们的源码可以看到很多方法用ModCount
判断结构
所以我们可以看出ArrayList、LinkedList、HashMap等是线程不安全的。
网友评论