Github user anmolnar commented on a diff in the pull request: https://github.com/apache/zookeeper/pull/584#discussion_r205950078 --- Diff: src/java/main/org/apache/zookeeper/server/DataTree.java --- @@ -478,7 +478,10 @@ public void createNode(final String path, byte data[], List<ACL> acl, HashSet<String> list = ephemerals.get(ephemeralOwner); if (list == null) { list = new HashSet<String>(); - ephemerals.put(ephemeralOwner, list); + HashSet<String> _list; + if ((_list = ephemerals.putIfAbsent(ephemeralOwner, list)) != null) { + list = _list; + } } synchronized (list) { --- End diff -- I'm not sure about that. ephemerals.putIfAbsent() is thread safe: it guarantees that newly created instance will be added to the HashMap only if the key is associated with a null value. Otherwise you will get the instance already present in the HashMap. Either case `list` will point to the one and only instance present in the hashmap. In your example when Step2 enters L483 it will get back the instance which was created and added to the HashMap by Step1 before it acquired the `list` lock. And that instance cannot be replaced in the HashMap with this code. After all `synchronized (list)` only guards access to the List, HashMap is guarded by putIfAbsent(). I still believe that `computeIfAbsent()` is more convenient and readable here.
---