ConcurrentHashMap put vs putIfAbsent

后端 未结 2 1968
既然无缘
既然无缘 2021-02-05 09:32

Java Docs says that, putIfAbsent is equivalent to

   if (!map.containsKey(key)) 
      return map.put(key, value);
   else
      return map.get(key         


        
2条回答
  •  无人及你
    2021-02-05 10:06

    So it doesnt update a key's value. is this correct?

    That is correct. It will return the current value that was already in the Map.

    would this be a better impl for adding and updating cache?

    A couple things would make your implementation better.

    1. You shouldn't use putIfAbsent to test if it exists, you should only use it when you want to ensure if one does not exist then putIfAbsent. Instead you should use map.get to test it's existence (or map.contains).

        V local = _cache.get(key);
        if (local.equals(value) && !local.IsExpired()) {
            return;
        }
    

    2. Instead of put you will want to replace, this is because a race condition can occur where the if can be evaluated as false by two or more threads in which one of the two (or more) threads will overwrite the other thread's puts.

    What you can do instead is replace

    When all is said and done it could look like this

    public void AddToCache(T key, V value) {
        for (;;) {
    
            V local = _cache.get(key);
            if(local == null){
                local = _cache.putIfAbsent(key, value);
                if(local == null)
                    return;
            }
            if (local.equals(value) && !local.IsExpired()) {
                return;
            }
    
            if (_cache.replace(key, local, value))
                return;
        }
    }
    

提交回复
热议问题