2
Map<String,Integer> m1 = new ConcurrentHashMap<>();
Map<String,Integer> m2 = new ConcurrentHashMap<>();
public void update(int i) {
  m1.put("key", i);
  m2.put("key", i);
}

In the dummy code above, the updates to m1 & m2 are not atomic. If I try to synchronize this block, findBugs complains "Synchronization performed on util.concurrent instance"

Is there a recommended way to do this other than not using concurrent collections and doing all synchronization explicitly.

As an aside I also don't know the exact implications of wrapping concurrent collections in explicit synchronization.

3
  • 2
    It's likely that you found a bug in FindBugs (pun intended) :) Commented May 7, 2015 at 18:41
  • 4
    This is an X-Y Problem you need to explain why you want to do this, because as is, this makes no semantic sense.
    – user177800
    Commented May 7, 2015 at 18:55
  • Having an atomic put-operation only makes sense if you have an atomic get-operation somewhere else.
    – isnot2bad
    Commented May 7, 2015 at 19:55

2 Answers 2

2

If the intention is that for a key both maps always retrieve the same value, the design of using two different concurrent maps is flawed. Even if you synchronize the write, reading threads can still access the two maps while youre writing. Thats probably what the FindBugs rule tries to catch.

There are two ways to go about this, either use explicit synchronization (that is two regular maps with synchronized reads and writes), or use just one concurrent map and put in a value object hold both ints.

1

A ConcurrentMap is not a synchronized map. The latter does indeed synchronizes on itself, so synchronizing on the Map will have an effect regarding other Map operations.

In contrast, a ConcurrentMap is designed to allow concurrent updates of different keys and does not synchronizes on itself, so if other code synchronizes on the Map instance, it has no effect. It wouldn’t help to use a different mutex; as long as other thread perform operations on the same maps without using this mutex, they won’t respect you intended atomicity. On the other hand, if all threads would use the mutex for all accesses to the maps, you wouldn’t need a ConcurrentMap anymore.

But as Jarrod Roberson noted, this is likely an X-Y Problem, as updating two maps atomically without having an atomic read of both maps, no thread would notice whether the update happened atomically or not. The question is what you actually want to achieve, either, you don’t really need the atomicity or you shouldn’t use ConcurrentMaps.

Not the answer you're looking for? Browse other questions tagged or ask your own question.