0

In many cases implementing double-checked-locking in Java is not thread safe (the unsynchronized section of code can return partially initialized values). However, I'm using double-checked locking to check if a value is in a ConcurrentHashMap, and if it isn't, then enter a synchronized block, create the object, and put it in the map. Is this thread safe? That is, will the put or get method in ConcurrentHashMap ever add or return partially constructed values (or do some other unexpected behavior)? Or are the get and put methods atomic, i.e. a successful put guarantees that other threads will see the properly constructed object that was put in the map? Code is as follows:

public class MyClass {

    private static ConcurrentHashMap<KeyObject, SingletonObject> myConcurrentMap = new Concurrent...

    ...

    private static SingletonValue getFromConcurrentMap(KeyObject key) {

        SingletonValue singleton = this.myConcurrentHashMap.get(key);
        if (singleton == null) {
            synchronized (this.myConcurrentHashMap) {
                singleton = this.myConcurrentHashMap.get(domainRuleBase);
                if (singleton == null) {
                    singleton = SingletonValue.buildNewInstance();
                    this.myConcurrentHashMap.put(key, singleton);
                }
            }
        }
        return singleton;
    }

    ...
}
RD_TRP
  • 11
  • 2
  • Also I would read this [doc](http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java.base/java/util/concurrent/ConcurrentHashMap.html) for more details. – nabster Apr 30 '20 at 01:19
  • I blv by double locking you can just use regular `HashMap` which is faster than `ConcurrentHashMap` – nabster Apr 30 '20 at 01:20
  • yes thanks, though what really convinced me was the [ConcurrentMap documentation](http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java.base/java/util/concurrent/ConcurrentMap.html): "memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentMap as a key or value happen-before actions subsequent to the access or removal of that object from the ConcurrentMap in another thread." – RD_TRP Apr 30 '20 at 01:39
  • This could almost, but not quite, be replaced by `myConcurrentHashMap.merge(key, SingletonValue.buildNewInstance(), (value, instance) -> value != null ? value : this.myConcurrentHashMap.getOrDefault(domainRuleBase, instance));` I would take a good look at `computeIfAbsent`, `putIfAbsent`, `merge`, and `getOrDefault` if I were you. A suitable application of those newer methods of `Map` may obviate the need for both the locking, tests, and logic. – David Conrad Apr 30 '20 at 01:42

0 Answers0