Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ConcurentMap keySet() question when map is modified and iterating over keyset

Quick background I have a concurrent map I used to cache some values that change quite often (still worth caching them from testing). I want to evict items from my cache at regular intervals by examining an expire time in the value. I am using the keySet() method to get a reference to all my keys and then check the values and if expired i remove them. In other threads the cache is being queried and updated(removed) constantly.

From the javadocs for keySet() it mentioned if the map changes while I am iterating over the keyset Set the results are undefined. Obviously I would like a defined way of dealing with this so the results are valid. Would it be enough to pass the Set to a HashSet and then iterate over this set as it is my understanding this set will not be backed by the map, is this a wasteful of memory way of doing it? Any ideas appreciated.

Unfortunately my evictor is not the only way for items to be removed from the concurrent map so am I correct in saying that I need to copy the keySet to another Set before iterating through it.

Thanks in advance

EDIT: It turns out I was reading the javadocs for the Map keySet() method instead of the ConcurrentMap keySet(). Thanks my bad :)

Returns a set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll retainAll, and clear operations. It does not support the add or addAll operations.

like image 512
Paul Whelan Avatar asked Mar 27 '09 11:03

Paul Whelan


People also ask

Can we update map while iterating in Java?

It is not allowed to modify a map in Java while iterating over it to avoid non-deterministic behavior at a later stage. For example, the following code example throws a java. util. ConcurrentModificationException since the remove() method of the Map interface is called during iteration.

Is map in Java thread-safe?

Maps are naturally one of the most widely style of Java collection. And, importantly, HashMap is not a thread-safe implementation, while Hashtable does provide thread-safety by synchronizing operations. Even though Hashtable is thread safe, it is not very efficient. Another fully synchronized Map, Collections.

How Does ConcurrentHashMap works in Java?

In ConcurrentHashMap, at a time any number of threads can perform retrieval operation but for updated in the object, the thread must lock the particular segment in which the thread wants to operate. This type of locking mechanism is known as Segment locking or bucket locking.

Is ConcurrentHashMap always thread-safe?

Concurrent. ConcurrentHashMap class achieves thread-safety by dividing the map into segments, the lock is required not for the entire object but for one segment, i.e one thread requires a lock of one segment. In ConcurrenHashap the read operation doesn't require any lock.


1 Answers

Are you using the Java Concurrent HashMap ? From the keySet() documentation it appears to behave in a fashion which you'd find useful.

Returns a set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations. The view's returned iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

i.e. you can remove stuff and you should be fine.

If you're not using this implementation, then which are you using (and why ? Not being funny, but it would be interesting to know why you've made that choice)

like image 196
Brian Agnew Avatar answered Sep 21 '22 18:09

Brian Agnew