Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Threadsafe way of exposing keySet()

Tags:

java

hashset

This must be a fairly common occurrence where I have a map and wish to thread-safely expose its key set:

public MyClass {
  Map<String,String> map = // ...
  public final Set<String> keys() {
     // returns key set
  }
}

Now, if my "map" is not thread-safe, this is not safe:

  public final Set<String> keys() {
     return map.keySet();
  }

And neither is:

  public final Set<String> keys() {
     return Collections.unmodifiableSet(map.keySet());
  }

So I need to create a copy, such as:

  public final Set<String> keys() {
     return new HashSet(map.keySet());
  }

However, this doesn't seem safe either because that constructor traverses the elements of the parameter and add()s them. So while this copying is going on, a ConcurrentModificationException can happen.

So then:

  public final Set<String> keys() {
     synchronized(map) {
       return new HashSet(map.keySet());
     }
  }

seems like the solution. Does this look right?

like image 328
Jake Avatar asked Jan 17 '11 02:01

Jake


People also ask

What kind of set does keySet return?

Example 2: keySet() Method in for-each Loop Here, the keySet() method returns a set view of all the keys. The variable key access each key from the view. Note: The Key of HashMap is of String type.

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.

How do you make an object thread-safe in Java?

Using Atomic Variable Using an atomic variable is another way to achieve thread-safety in java. When variables are shared by multiple threads, the atomic variable ensures that threads don't crash into each other.


1 Answers

That solution isn't particularly helpful unless you plan to also synchronize on the map everywhere it is used. Synchronizing on it doesn't stop someone else from invoking methods on it at the same time. It only stops them from also being able to synchronize on it.

The best solution really seems to be just use ConcurrentHashMap in the first place if you know you need concurrent puts and removes while someone may be iterating. If the concurrency behavior that class offers isn't what you need, you'll probably just need to use a fully synchronized Map.

like image 139
Affe Avatar answered Oct 05 '22 23:10

Affe