简介

快速失败机制 一文中,大致说明了在 java.util 中集合内实现的快速失败机制,并在最后指出,一旦多个线程操作同一个集合,就有可能触发 ConcurrentModificationException 异常。

安全失败机制与快速失败机制差不多,但快速失败是为了检测并发修改的 bug,而安全失败机制是为了解决这种 bug 提供一种解决方案。

源码

我还是用 HashMap 的线程安全集合 ConcurrentHashMap 的源码介绍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public final Iterator<V> iterator() {
ConcurrentHashMap<K,V> m = map;
Node<K,V>[] t;
int f = (t = m.table) == null ? 0 : t.length;
return new ValueIterator<K,V>(t, f, 0, f, m);
}


public Iterator<K> iterator() {
Node<K,V>[] t;
ConcurrentHashMap<K,V> m = map;
int f = (t = m.table) == null ? 0 : t.length;
return new KeyIterator<K,V>(t, f, 0, f, m);
}


public Iterator<Map.Entry<K,V>> iterator() {
ConcurrentHashMap<K,V> m = map;
Node<K,V>[] t;
int f = (t = m.table) == null ? 0 : t.length;
return new EntryIterator<K,V>(t, f, 0, f, m);
}

由上面的源码可以看出,当需要对集合进行遍历的时候,会先将当前的 map 复制一份:ConcurrentHashMap<K,V> m = map,然后遍历的就是这个集合,当其他线程对这个集合做操作时,并不会影响遍历过程。

可能会出现的问题

当两个线程,一个线程在读,一个线程在操作集合,就会出现读出来的数据和集合中实际的数据不一致的问题。