A DESCRIPTION OF THE PROBLEM : ConcurrentHashMap.putIfAbsent holds a lock for the duration of the compound action it's described in terms of, though my experience suggests that people assume that the "get" part is done without locking, and a lock is only taken if an insertion appears necessary. also, if calling code is expected to make the optimistic call to ConcurrentHashMap.get in cases where it's likely the mapping is already present, it would be worth mentioning this in the documentation. here's a suggested patch: --- ConcurrentHashMap.java 2007-10-31 14:20:31.000000000 -0700 +++ ConcurrentHashMap.java 2008-08-13 21:28:08.000000000 -0700 @@ -912,7 +912,27 @@ } /** - * {@inheritDoc} + * If the specified key is not already associated + * with a value, associate it with the given value. + * This is equivalent to + * <pre> + * if (!map.containsKey(key)) + * return map.put(key, value); + * else + * return map.get(key);</pre> + * except that the action is performed atomically, and with a lock + * held for the duration of the action. + * + * The recommended idiom is thus + * <pre> + * if (map.get(key) == null) + * map.putIfAbsent(key, value);</pre> + * if the key is likely to have already been associated with a value + * because the normal case will then involve no locking. + * + * @param key key with which the specified value is to be associated + * @param value value to be associated with the specified key + * * * @return the previous value associated with the specified key, * or <tt>null</tt> if there was no mapping for the key EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - see diff. ACTUAL - see diff. URL OF FAULTY DOCUMENTATION : http://java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html
|