[concurrency-interest] How to implement a self populating memoizer cache?

Nader Aeinehchi nader at aeinehchi.com
Wed Nov 3 16:47:49 EDT 2010


Dear Kevin,

If I understand you correctly, MapMaker.ExpiringComputingMap (which I 
believe you are referring to) is thread safe.  Furthermore, it 
guarantees that threads will wait until the first thread computes for a 
given key.

Following is an excerpt of MapMaker.ExpiringComputingMap.  Here, if the 
result is null, the compute method is called and the calculated value is 
put.  How is it guaranteed that another thread does not concurrently 
perform the latter (calculation and put operations)?  Is not this a 
read-modify-write scheme which according to JCiP book is a compound (not 
atomic) operation?

In advance, thank you very much.


     @Override
     public V get(Object k) {
       // from CustomConcurrentHashMap
       V result = super.get(k);
       if (result == null && computer != null) {
         /*
          * This cast isn't safe, but we can rely on the fact that K is 
almost
          * always passed to Map.get(), and tools like IDEs and Findbugs can
          * catch situations where this isn't the case.
          *
          * The alternative is to add an overloaded method, but the 
chances of
          * a user calling get() instead of the new API and the risks 
inherent
          * in adding a new API outweigh this little hole.
          */
         @SuppressWarnings("unchecked")
         K key = (K) k;
         result = compute(key);
       }
       return result;
     }

     private V compute(K key) {
       // from MapMaker
       V value;
       try {
         value = computer.apply(key);
       } catch (Throwable t) {
         throw new ComputationException(t);
       }

       if (value == null) {
         String message = computer + " returned null for key " + key + ".";
         throw new NullPointerException(message);
       }
       put(key, value);
       return value;
     }



On 11/03/2010 03:15 PM, Kevin Bourrillion wrote:
> On Wed, Nov 3, 2010 at 5:31 AM, Nader Aeinehchi <nader at aeinehchi.com 
> <mailto:nader at aeinehchi.com>> wrote:
>
>     1. Please forgive me for my ignorance, but ExpiringComputingMap
>     does not guarantee that a computable to be calculated only once
>     for concurrent threads?
>
>
> "|Map.get(java.lang.Object)| 
> <http://java.sun.com/javase/6/docs/api/java/util/Map.html?is-external=true#get%28java.lang.Object%29> 
> either returns an already-computed value for the given key, atomically 
> computes it using the supplied function, or, if another thread is 
> currently computing the value for this key, simply waits for that 
> thread to finish and returns its computed value. Note that the 
> function may be executed concurrently by multiple threads, but only 
> for distinct keys."
>
>
> -- 
> Kevin Bourrillion @ Google
> http://guava-libraries.googlecode.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20101103/d72fd3b7/attachment.html>


More information about the Concurrency-interest mailing list