2

I have a static hashMap, shared with multiple threads. I am not iterating the map at all but just uses the get, put, remove. Is it safe from ConcurrentModificationException ?

The method looks like this

private static Map<Long, Integer> TRACKER = new HashMap<Long,Integer>();
public static void track(Long tid, boolean b) {
        if (b) {
            if (TRACKER.containsKey(tid)) {
                TRACKER.put(tid, TRACKER.get(tid) + 1);
            } else {
                TRACKER.put(tid, 1);
            }
        } else {
            Integer n = TRACKER.get(tid);
            if (n != null) {
                n = n -1;
                if (n == 0) {
                    TRACKER.remove(tid);
                } else {
                    TRACKER.put(tid, n);
                }
            }
        }
    }
Anthony C
  • 2,117
  • 2
  • 15
  • 26
  • 1
    There's nothing in the code you're showing us here to cause a ConcurrentModificationException. – khelwood Sep 06 '18 at 23:41
  • 1
    Nothing will cause a concurrent modification exception...and that's *bad,* because concurrent modification is happening, and breaking things, but it can't figure it out and throw an exception to warn you. – Louis Wasserman Sep 07 '18 at 03:48

2 Answers2

4

If multiple threads are performing get, put & remove operations on a HashMap, without proper synchronization, some bad things like size() reporting missing / lost entries, unexpected NPEs ... even infinite loops may happen.

HashMap documentation says -

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) ...

Thanks Stephen.

Saketh Katari
  • 332
  • 2
  • 11
  • 1
    You probably could update the values concurrently without synchronization after reading those docs, But I can't imaging the mechanisms needed to do the checks required to update the value without accidentally putting a new value. It would have to be incredibly contrived. – Ryan Leach Sep 07 '18 at 01:52
3

Is it safe from ConcurrentModificationException?

It is safe from ConcurrentModificationException. That exception is only thrown by methods that iterate (in some sense) the map or one of its views using a conventional iterator or a spliterator.

However, since HashMap is not a thread-safe class, if you use it from multiple threads without proper external external synchronization, bad things can happen. These include (in order of increasing badness)

  1. The size() method reporting the wrong value.
  2. Entries mysteriously disappearing, either temporarily or permanently.
  3. Possible NPEs and other unchecked exceptions.
  4. Possible infinite loops due to an unfortunate sequence of operations by multiple threads creating a loop in a hash chain.

Your example code is unsafe ... but you won't get a "fast fail" ConcurrentModificationException. Instead you are likely to get inexplicable errors at "random" times that are difficult to reproduce.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216