Matthias Schroer
Matthias Schroer

Reputation: 123

How to update a Value in a ConcurrentHashMap threadsafe

I need to update a value in a ConcurrentHashmap but I am not sure on how to do this thread safe.

The Hashmap is a ConcurrentHashMap and I need to get the instance of the custom class, perform some operations on it and then put the updated value back in.

Is there any way to combine this get-alter-put operation to something atomic?

Thanks in advance

Upvotes: 6

Views: 14145

Answers (3)

Mitesh Joshi
Mitesh Joshi

Reputation: 187

I would say you can use

map.compute(key,  (k,v) -> {
                      if(k != null) {
                        return v+1;
                      } else {
                        return some_var;
                      }
                    });

Upvotes: 1

prasad_
prasad_

Reputation: 14317

A ConcurrentHashMap's computeIfPresent method is a possibility. From the javadocs: If the value for the specified key is present, attempts to compute a new mapping given the key and its current mapped value. The entire method invocation is performed atomically (expects that computation should be short and simple).

How does the method work, in general? Some example code:

Consider a Map<String, Integer> map with keys and values: {four=4, one=1, ten=10, two=2, three=3, five=5, eleven=11}

(1) updates the mapping with new value (note the lambda is a BiFunction returning a newly computed value):

map.computeIfPresent("ten", (k, v) -> new Integer(100));

(2) the function returns a null, the existing mapping is removed:

map.computeIfPresent("eleven", (k, v) -> null);

(3) the mapping is not added, as there is no existing mapping:

map.computeIfPresent("twenty", (k, v) -> new Integer(20));

EDIT:

Note on compute(): Using the same input map data (and method arguments), the compute method works similarly but for the case 3. Note the case 3 where new mappings can be added:

(3) a new mapping is added.

Upvotes: 2

Debapriya Biswas
Debapriya Biswas

Reputation: 1349

You can use ConcurrentHashMaps computeIfPresent https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfPresent-K-java.util.function.BiFunction-

But since computeIfPresent is a costly operation as its atomic and some update operations will be blocked by other threads during the computation of the BiFunction . You can preclude this with a read operation on concurrent hashmap which is pretty fast and if that returns not null , invoke computeIfPrsent

Below code gets the value of key "1" and adds 100 to it and puts in back to the map in a atomic way

ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
        map.put(1,100);
        Integer value = map.get(1);
        if (value != null)
            map.computeIfPresent(1, (key, oldValue) -> oldValue + 100);
    }

Upvotes: -1

Related Questions