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.


---

Reply via email to