javamultithreadingconcurrenthashmap

Is it strictly necessary to use atomic integer inside a compute block?


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.


Solution

  • Your example is flawed because return count++; increments count but returns the previous value - i.e. it never counts up. That line should be return count + 1;:

    counters.compute(key, (k, count) -> {
        if (count == null) {
            return 1;
        } else {
            return count+1;
        }
    });
    

    Note that this usage of ConcurrentHashMap.compute() (with Integer as value) is inherently thread safe:


    Using the merge() method leads to an even simpler solution (thanks to David Conrad for the hint):

    counters.merge(key, 1, Math::addExact);
    

    This throws an ArithmeticException if the counter would overflow. If you want to allow the counter to overflow you can use

    counters.merge(key, 1, Integer::sum);