[concurrency-interest] Bug in ConcurrentHashMap

Eric Zoerner eric.zoerner@gemstone.com
Fri, 21 Nov 2003 13:26:41 -0800


It is fine to add that test case to the tests, but keep in mind that it is very 
dependent on the sizing and hash algorithms that are currently used in the map 
in order to get a reference to an entry that would be cloned.
Also, it was not strictly necessary to remove the key from a separate thread, of 
course, but I wanted it to reflect a more believable scenario.

Use cases for putIfPresent come up when the existence of a key in the map has 
significance beyond what the value associated with the key is. One such use case 
  is when the map is used for caching data from a relational database and the 
presence of the key in the map may provide a hint that the corresponding row 
exists in the database*, or it may provide the ability to enumerate the names of 
all known documents, etc., without necessarily having the value in the map at 
the moment. To free up memory in the cache you may want to replace the value in 
the map with a placeholder indicating that the value is now invalid and needs to 
be retrieved from the database again the next time it is requested (let's call 
the placeholder object INVALID). However, you don't want  to lose the 
information that the key exists. So you want to put(key, INVALID). But this 
should not create a new key in the map if that key was just legitimately removed 
from the map (and the database, e.g. by another thread). So in this case you 
would want call putIfPresent(key, INVALID). I'm sure there are other ways of 
implementing this use case, but this is a case where a putIfPresent method would 
indeed be useful.
I have other, more complicated use cases where putIfPresent would be useful, but 
hopefully this simple one suffices to make the point.

Thanks for fixing the setValue bug so quickly, by the way!

- Eric

* The presence of the key might provide a hint as to whether a CREATE or UPDATE 
is necessary when synchonizing with a RDBMS


Doug Lea wrote:

> A better way to do this was to apply the tactics we used in
> IdentityHashMap of making EntrySet entries mere forwarders (but still
> more efficiently handling the more common keySet and Values
> iterators).  As is now checked in.
> 
> Eric: Is it OK fow us to add your test case to JSR166 tests?
> 
> I didn't answer before:
> 
> 
>>Which leads me to another comment. It would be useful to have a "putIfPresent"
>>method on ConcurrentMap in addition to the putIfAbsent that is already there,
>>for the case where you require the entry to already exist when replacing a
>>value.
> 
> 
> Can you give a good use case? I can't think of any. 
> 
> -Doug