5

I am trying to see actual Java documentation describing the behavior of how many times mappingFunction can be called when passed to ConcurrentHashMap.computeIfAbsent and ConcurrentHashMap.computeIfPresent methods.

The Javadoc of ConcurrentHashMap.computeIfAbsent seems pretty clear in saying that the mappingFunction will be executed at most once:

Javadoc for ConcurrentHashMap.computeIfAbsent

If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. The entire method invocation is performed atomically, so the function is applied at most once per key. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.

But the Javadoc for ConcurrentHashMap.computeIfPresent does not say anything about how many times mappingFunction can be executed:

Javadoc for ConcurrentHashMap.computeIfPresent

If the value for the specified key is present, attempts to compute a new mapping given the key and its current mapped value. The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.

By looking at the source code they both look like that mappingFunction will be executed at most once. But I would really like to see actual documentation guaranteeing that behavior.

Is there such a documentation?

tsolakp
  • 5,858
  • 1
  • 22
  • 28
  • this would not be the first time something is not correct in the documentation... https://stackoverflow.com/questions/46272108/wrong-implementation-of-oracle-java-concurrenthashmap – Eugene Feb 04 '18 at 15:05

1 Answers1

3

In the documentation for ConcurrentMap#computeIfPresent, we see the following:

The default implementation is equivalent to performing the following steps for this map:

for (V oldValue; (oldValue = map.get(key)) != null; ) {
    V newValue = remappingFunction.apply(key, oldValue);
    if ((newValue == null)
        ? map.remove(key, oldValue)
        : map.replace(key, oldValue, newValue))
     return newValue;
 }
 return null;

Even though the documentation doesn't explicitly say that the remapping function will only be executed once, the equivalent code that the documentation provides makes that clear.

Note: Keep in mind that:

When multiple threads attempt updates, map operations and the remapping function may be called multiple times.

(emphasis mine)

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • 2
    Thanks. But that code is just for documenting how implementation might use `remappingFunction` and is not thread safe, is actual quite different then the code used in `ConcurrentHashMap` and does not give clear answer as to how many times `remappingFunction` might be called in actual multi threaded implementation. – tsolakp Feb 02 '18 at 17:13
  • 2
    I'm not sure if you saw the most recent edit, but the documentation states "When multiple threads attempt updates, map operations and the **remapping function may be called multiple times**." – Jacob G. Feb 02 '18 at 17:14
  • Yes, but is it from actual documentation or is just your own opinion. Because `computeIfAbsent` updates map but also guarantees that "remapping function" wont be called more then once. – tsolakp Feb 02 '18 at 17:16
  • 2
    It's from the documentation! Read the link in my answer. – Jacob G. Feb 02 '18 at 17:17
  • 1
    Thanks. That is what I was looking for. – tsolakp Feb 02 '18 at 17:20
  • @JacobG. sounds like a bug in the documentation to me, as such, you should highlight that as the very first sentence, in bold. Or better, open a ticket and link it to the answer – Eugene Feb 04 '18 at 15:10
  • @Eugene I can’t see, where the documentation is wrong. In contrast, I can’t follow the logic of this answer. It shows a piece of code that clearly contains a loop, followed by the contradicting statement that this code made it “clear” that the function is “executed once”. – Holger Feb 06 '18 at 10:17
  • @Holger oh god thank you, I was just reading this question/answer after seeing the other one from you and could not make any sense in either my comment or the answer... – Eugene Feb 06 '18 at 10:19