Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomically incrementing counters stored in ConcurrentHashMap

I would like to collect some metrics from various places in a web app. To keep it simple, all these will be counters and therefore the only modifier operation is to increment them by 1.

The increments will be concurrent and often. The reads (dumping the stats) is a rare operation.

I was thinking to use a ConcurrentHashMap. The issue is how to increment the counters correctly. Since the map doesn't have an "increment" operation, I need to read the current value first, increment it than put the new value in the map. Without more code, this is not an atomic operation.

Is it possible to achieve this without synchronization (which would defeat the purpose of the ConcurrentHashMap)? Do I need to look at Guava ?

Thanks for any pointers.


P.S.
There is a related question on SO (Most efficient way to increment a Map value in Java) but focused on performance and not multi-threading

UPDATE
For those arriving here through searches on the same topic: besides the answers below, there's a useful presentation which incidentally covers the same topic. See slides 24-33.

like image 262
wishihadabettername Avatar asked Jul 26 '10 23:07

wishihadabettername


People also ask

How do you atomically update a value in ConcurrentHashMap?

The compute(Key, BiFunction) method of ConcurrentHashMap class is used to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping is found). This method is used to atomically update a value for given key in ConcurrentHashMap.

Why ConcurrentHashMap is faster than HashMap?

HashMap performance is relatively high because it is non-synchronized in nature and any number of threads can perform simultaneously. But ConcurrentHashMap performance is low sometimes because sometimes Threads are required to wait on ConcurrentHashMap.

What is the use of ConcurrentHashMap () in multithreading?

ConcurrentHashMap class is thread-safe i.e. multiple threads can operate on a single object without any complications. At a time any number of threads are applicable for a read operation without locking the ConcurrentHashMap object which is not there in HashMap.

How many threads can ConcurrentHashMap read?

By default ConcurrentHashMap has segment array size as 16 so simultaneously 16 Threads can put data in map considering each thread is working on separate Segment array index.


2 Answers

In Java 8:

ConcurrentHashMap<String, LongAdder> map = new ConcurrentHashMap<>();  map.computeIfAbsent("key", k -> new LongAdder()).increment(); 
like image 146
ZhekaKozlov Avatar answered Sep 19 '22 20:09

ZhekaKozlov


Guava's new AtomicLongMap (in release 11) might address this need.

like image 28
Louis Wasserman Avatar answered Sep 18 '22 20:09

Louis Wasserman