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:

  1. map contains mapping: 'a'->0
  2. deleting thread starts executing map.entryset().removeif(entry->entry.getvalue()==0)
  3. deleting thread calls .iteratator() inside removeif call , gets iterator reflecting current state of collection
  4. another thread executes map.put('a', 1)
  5. deleting thread still sees 'a'->0 mapping (iterator reflects old state) , because 0==0 true decides remove key map.
  6. the map contains 'a'->1 deleting thread saw old value of 0 , '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

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -