众所周知,ConcurrenthashMap类允许我们安全地使用迭代器。据我所知,Map
的来源是通过将当前Map
状态存储到迭代器本身来实现的。这是表示迭代器的内部类(在调用iterator()
时创建了一个子项):
abstract class HashIterator {
int nextSegmentIndex;
int nextTableIndex;
HashEntry<K,V>[] currentTable;
HashEntry<K, V> nextEntry;
HashEntry<K, V> lastReturned;
//Methods and ctor
}
但是如果某个线程在迭代器的构造过程中写入了Map呢?那么我们是否得到了地图的非威慑状态?
事情既不是Map的同步方法。 ReentrantLock
方法有put
,但就是这样(据我所知)。所以,我不明白迭代器如何支持一个正确的状态,即使一些线程在构造过程中写入地图?
答案 0 :(得分:3)
迭代器提供弱一致的状态。它没有提供数据的事务视图。它只提供你会看到所有键/值,如果它没有被改变,如果是,你可能会或可能不会看到这种改变,但你不会得到错误。
答案 1 :(得分:2)
来自ConcurrentHashMap
的<{3}}:
检索操作(包括get)一般不会阻塞,所以可能 与更新操作重叠(包括put和remove)。检索 反映最近完成的更新操作的结果 坚持他们的发作。对于诸如putAll和。之类的聚合操作 清除,并发检索可能仅反映插入或删除 一些条目。同样,Iterators和Enumerations返回元素 反映哈希表的状态在某个时刻或之后的某个时刻 创建迭代器/枚举。他们不扔 ConcurrentModificationException的。 但是,迭代器的设计是 一次仅由一个线程使用。
现在回答问题。
但是如果某个线程在Map期间写入了什么呢? 构造迭代器?
如上所述,迭代器代表某个时间点的状态。所以它可能不是最近的州。
即使某个线程,迭代器如何支持正确的状态 在构造过程中写入地图?
保证在迭代期间放置/删除时不会破坏。但是,无法保证一个线程会看到另一个线程执行的映射更改(无需从映射中获取新的迭代器)。迭代器保证在创建时反映地图的状态。未来的变化可能会反映在迭代器中,但它们并非必须如此。