My doubt is simple. According to other posts this is not thread safe because of the reading+write operation count++. But a compute as far as I know, blocks the entire sector for that key inside the map. So it's impossible that two threads performs this operation at the same time. Why should I use atomic integer or any other concurrent object?
Key can be a profile and the counter it's just a counter for something that can be numeric. Posts, messages, likes... The structure is a ConcurrentHashMap<Key,Integer>.
counters.compute(key, (key, counter) -> {
if (counter == null) {
return 1;
} else {
return count++;
}
});
I didn't find any issue executing threads in some tests. But still I don't understand why should I use atomic integer.
Your example is flawed because
return count++;incrementscountbut returns the previous value - i.e. it never counts up. That line should bereturn count + 1;:Note that this usage of
ConcurrentHashMap.compute()(withIntegeras value) is inherently thread safe:compute()function is atomically executed for a specific key - i.e. no other thread can callcompute()for the same key at the same time and therefore you cannot loose an update.get()calls either see the old or the new value depending on the exact timing but (sinceIntegeris immutable) they cannot corrupt the count.Using the
merge()method leads to an even simpler solution (thanks to David Conrad for the hint):This throws an
ArithmeticExceptionif the counter would overflow. If you want to allow the counter to overflow you can use