java - Behavior of entrySet().removeIf in ConcurrentHashMap -
i use concurrenthashmap let 1 thread delete items map periodically , other threads put , items map @ same time.
i'm using map.entryset().removeif(lambda)
in removing thread. i'm wondering assumptions can make behavior. can see removeif
method uses iterator go through elements in map, check given condition , remove them if needed using iterator.remove()
.
documentation gives info concurrenthashmap iterators behavior:
similarly, iterators, spliterators , enumerations return elements reflecting state of hash table @ point @ or since creation of iterator/enumeration. hey not throw concurrentmodificationexception. however, iterators designed used 1 thread @ time.
as whole removeif
call happens in 1 thread can sure iterator not used more 1 thread @ time. still i'm wondering if course of events described below possible:
- map contains mapping:
'a'->0
- deleting thread starts executing
map.entryset().removeif(entry->entry.getvalue()==0)
- deleting thread calls
.iteratator()
insideremoveif
call , gets iterator reflecting current state of collection - another thread executes
map.put('a', 1)
- deleting thread still sees
'a'->0
mapping (iterator reflects old state) , because0==0
true decides remove key map. - the map contains
'a'->1
deleting thread saw old value of0
,'a' ->1
entry removed though shouldn't be. map empty.
i can imagine behavior may prevented implementation in many ways. example: maybe iterators not reflecting put/remove operations reflecting value updates or maybe remove method of iterator checks if whole mapping (both key , value) still present in map before calling remove on key. couldn't find info of things happening , i'm wondering if there's makes use case safe.
i managed reproduce such case on machine. think, problem entrysetview
(which returned concurrenthashmap.entryset()
) inherits removeif
implementation collection
, , looks like:
default boolean removeif(predicate<? super e> filter) { objects.requirenonnull(filter); boolean removed = false; final iterator<e> each = iterator(); while (each.hasnext()) { // `test` returns `true` entry if (filter.test(each.next())) { // entry has been changed, `test` return `false` each.remove(); // ...but still remove removed = true; } } return removed; }
in humble opinion, cannot considered correct implementation concurrenthashmap
.
Comments
Post a Comment