[concurrency-interest] conditional put

Kevin Condon conivek at gmail.com
Wed Nov 7 13:24:49 EST 2007


A while back I developed a ConcurrentCreationMap class to encapsulate
this type of behavior.  It is a Map implementation that adds a
createIfAbsent(key, factory) method, with usage like this:

// implement the required factory interface
ConcurrentCreationMapValueFactory<K,V> factory =
    new ConcurrentCreationMapValueFactory<K,V>() {
  public V createInstance(K key) { ... }
  public long creationTimeout() { ... }
};
...
ConcurrentCreationMap<K,V> map = new ConcurrentCreationMap<K,V>();
...
K key = ...;
V value = map.get(key);
if (value == null) {
  value = map.createIfAbsent(key, factory);
  if (value == null) {
    // creation failed or timed out waiting for another thread to create
  }
}

The implementation uses internally a ConcurrentHashMap to hold the
values and delegates other map operations directly to it.  Well,
almost directly.  The internal map values are actually a Map.Entry
implementation whose getValue() blocks until setValue() is invoked
with the created value (by the createIfAbsent() logic), or until the
factory timeout expires.  Due to this Map.Entry wrapper, the delegated
map operations and iterators have to unwrap the internal map.get()
returned value.  The internal Map.Entry implementation is where all
the synchronization occurs and is the key to limiting contention only
to accessing the value being created without blocking the entire map,
as well as enforcing creation atomicity.

I wish I had thought of using a FutureTask at the time I developed
this class.  It could be easily retrofitted by creating the FutureTask
in createIfAbsent() and then doing a get() with the specified factory
timeout.  That's almost cool enough to do the retrofit on just the
merits of elegance alone.

I like having the behavior encapsulated into its own class, just to
keep from duplicating the logic over and over.  Also, it encouraged me
to create unit tests for the class, which means I could do the
FutureTask retrofit and be pretty confident that I didn't break
anything in the process.

Regards,
Kevin


More information about the Concurrency-interest mailing list