1
votes

I'm using Spring cache abstraction with Guava cache. I have a method with @Cacheable annotation and parameter (that serves as a cache key) to put values into the cache. But this method is accessed in a multi threaded env so there are multiple concurrent calls to the method with the same parameter value. So that means the same logic that creates the value to be cached is done for the same cache key multiple times and put into the cache multiple times concurrently. It'd be much more efficient if for each parameter value (cache key) the method would be called only once and put into the cache once. Can Spring handle such a scenario?

1
Is program logic necessary to initialize the cache, or can the cache's entries be configured in the application context? - Keith
Have you confirmed that this actually happens, or do you just think it works that way? Because Guava caches don't work that way. The value is loaded a single time. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…: If another call to get(K) or getUnchecked(K) is currently loading the value for key, simply waits for that thread to finish and returns its loaded value - JB Nizet
@JBNizet I think he's concerned about multiple threads calling put and overwriting the same key/value. I'm wondering if this is just solved by using putIfAbsent(...) - Keith
Unfortunately both Spring and JSR-107 cache annotations do not atomically compute the value. Instead they race on get-compute-put. This is intentional, though I strongly disagree and consider it faulty reasoning. - Ben Manes
@mike27 I searched Spring's issue tracker SPR-11540 rationalizes the lack of support by saying (1) you should preload the cache with everything and (2) it would be too complex to implement. Both are invalid answers, as the easiest approach would be to use a simple array of locks, hash in, and lock around the get/put call (with a get outside to bypass the lock if found). Ideally they would delegate to the cache implementation for a more optimal version. Preloading the entire world defeats the purpose of a cache, imho. - Ben Manes

1 Answers

1
votes

As of Spring Framework 4.3 (still in early development phase at the time of writing) a new flag on @Cacheable called sync is available. If you enable that flag, you opt-in for basically what you're asking.

Spring Framework 4.3 GA is due around May next year but you should see a first milestone in Q1 2016 still. Please give that a try and let us know if that works for you.