ConcurrentHashMap atomic get, increment and replace

5.1k views Asked by At

Is there an easy way to get, increment and replace an integer from a ConcurrentHashMap?

ConcurrentHashMap<MyResource, AtomicInteger> map;

Let's say that every value has already been initialized like this:

map.get(i) = new AtomicInteger(0);

and that we do not add any new keys.

How can I make a get, increment and replace atomic (and thread safe)?

Something like this, should not work:

map.get(myResourceKey).incrementAndGet();

Because 2 threads could get the same integer before incrementing it right?

The map is keeping track of how many threads are using a certain resource. And I want something to happen only when a resource is not used (counter = 0).

2

There are 2 answers

1
JP Moresmau On

The AtomicInteger will work fine with multiple threads, that's its purpose. So if the map doesn't change, you're fine.

Problems will occur if several threads try to modify the map at the same time, for example two threads adding each their own AtomicInteger. In this case, synchronize the map itself.

0
Kenny Colliander Nordin On

You can use compute to perform atomic operations like the one you're asking for. The compute method will return the incremented value or 1 if it's the first call.

ConcurrentMap<MyResource, Integer> map = new ConcurrentHashMap<>();

map.compute(resourceKey, (k, v) -> v == null ? 1 : v + 1);