简体   繁体   中英

Java Concurrency: HashMap Vs ConcurrentHashMap when concurrent threads only remove elements

i have a main thread that creates a HashMap, adds multiple runnable objects to it and then starts each runnable (passing the HashMap to each). The runnable removes its object from the map just before it is about to finish processing.

I would like to know if there is any reason to use a ConcurrentHashMap (rather than a HashMap) in this case - the only operation the runnables perform on the map is to remove themselves from it. Is there a concurrency consideration that necessitates the use of ConcurrentHashMap in this case?

Main thread

private final Map<Integer, Consumer> runnableMap = new HashMap<>();

Runnable runnable;

for (int i = 1; i <= NUM_RUNNABLES; i++) {
    runnable = new Consumer(i, runnableMap);
    runnableMap.put(i, runnable);
    executionContext.execute(runnable);
}

Consumer implements Runnable

private final Integer consumerNumber;
private final Map<Integer, Consumer> runnableMap;

public Consumer(int consumerNumber, final Map<Integer, Consumer> runnableMap){
    this.consumerNumber = consumerNumber;
    this.runnableMap = runnableMap;
}

public void run() {
    :::
    // business logic
    :::
    // Below remove is the only operation this thread executes on the map
    runnableMap.remove(consumerNumber);
}

If your reason for doing this is to track thread completion, why not use a CountdownLatch? Not sure if a HashMap can have concurrency issues only on remove, I recommend use it only if your code will not break on any possible issue, or go with a ConcurrentHashMap.

You asked about differences between HashMap and ConcurrentHashMap , but there is an additional data structure to consider: Hashtable . There are differences and trade-offs for each. You will need to evaluate which is the best fit for your intended usage.

  • HashMap is unsynchronized, so if more than one thread can read from or write to it, your results will be unpredictable. HashMap also permits null as key or value.

  • Hashtable is synchronized, doesn't support null keys or values. From the Hashtable Javadoc :

    Hashtable is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap in place of Hashtable. If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap in place of Hashtable.

  • ConcurrentHashMap is thread-safe, doesn't allow null to be used as a key or value.

The javadoc of HashMap says:

Note that this implementation is not synchronized.

If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map.

As mentioned above, deletion is a structural change and you must use synchronization.

Furthermore, in the removeNode() method of Hashmap (which is called by the remove() method), the modCount variable is incremented, which is responsible for ConcurrentModificationException . So you might get this exception if you remove elements without synchronization.

Therefore you must use a ConcurrentHashMap .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM