EntrySet().removeIf 在 ConcurrentHashMap 中的行为
我想使用 ConcurrentHashMap 让一个线程定期从映射中删除一些项目,让其他线程同时从映射中放置和获取项目。
我在删除线程中使用。我想知道我能对它的行为做出什么假设。我可以看到该方法使用迭代器来遍历映射中的元素,检查给定的条件,然后在需要时使用.map.entrySet().removeIf(lambda)
removeIf
iterator.remove()
文档提供了有关 ConcurrentHashMap 迭代器行为的一些信息:
类似地,迭代器、拆分器和枚举返回的元素反映了在创建迭代器/枚举时或自创建以来哈希表的状态。嘿,不要抛出 ConcurrentModificationException。但是,迭代器设计为一次只能由一个线程使用。
由于整个调用发生在一个线程中,我可以确保迭代器当时没有被多个线程使用。我仍然想知道下面描述的事件过程是否可能:removeIf
- 地图包含映射:
'A'->0
- 删除线程开始执行
map.entrySet().removeIf(entry->entry.getValue()==0)
- 删除调用内部的 Thread 调用,并获取反映集合当前状态的迭代器
.iteratator()
removeIf
- 另一个线程执行
map.put('A', 1)
- 删除线程仍然看到映射(迭代器反映旧状态),并且由于是真的,它决定从映射中删除A键。
'A'->0
0==0
- 地图现在包含但删除线程看到的旧值,并且条目被删除,即使它不应该是。地图为空。
'A'->1
0
'A' ->1
我可以想象,实现可能会以多种方式阻止这种行为。例如:迭代器可能不反映 put/remove 操作,但总是反映值更新,或者迭代器的 remove 方法在对键调用 remove 之前检查整个映射(键和值)是否仍存在于映射中。我找不到有关发生的任何这些事情的信息,我想知道是否有某些东西使该用例安全。