A blocking decorator for an Ehcache, backed by a {@link Ehcache}.
It allows concurrent read access to elements already in the cache. If the element is null, other reads will block until an element with the same key is put into the cache.
This is useful for constructing read-through or self-populating caches.
This implementation uses the {@link Mutex} class from Doug Lea's concurrency package. If you wish to usethis class, you will need the concurrent package in your class path.
It features:
- Excellent liveness.
- Fine-grained locking on each element, rather than the cache as a whole.
- Scalability to a large number of threads.
This class has been updated to use Lock striping. The Mutex implementation gives scalability but creates many Mutex objects of 24 bytes each. Lock striping limits their number to 100.
A version of this class is planned which will dynamically use JDK5's concurrency package, which is based on Doug Lea's, so as to avoid a dependency on his package for JDK5 systems. This will not be implemented until JDK5 is released on MacOSX and Linux, as JDK5 will be required to compile it, though any version from JDK1.2 up will be able to run the code, falling back to Doug Lea's concurrency package, if the JDK5 package is not found in the classpath.
The
Mutex
class does not appear in the JDK5 concurrency package. Doug Lea has generously offered the following advice:
"You should just be able to use ReentrantLock here. We supply ReentrantLock, but not Mutex because the number of cases where a non-reentrant mutex is preferable is small, and most people are more familiar with reentrant seamantics. If you really need a non-reentrant one, the javadocs for class AbstractQueuedSynchronizer include sample code for them."
-Doug
"Hashtable / synchronizedMap uses the "one big fat lock" approach to guard the mutable state of the map. That works, but is a big concurrency bottleneck, as you've observed. You went to the opposite extreme, one lock per key. That works (as long as you've got sufficient synchronization in the cache itself to protect its own data structures.)
Lock striping is a middle ground, partitioning keys into a fixed number of subsets, like the trick used at large theaters for will-call ticket pickup -- there are separate lines for "A-F, G-M, N-R, and S-Z". This way, there are a fixed number of locks, each guarding (hopefully) 1/Nth of the keys." - Brian Goetz
Further improvements to hashing suggested by Joe Bowbeer.
@author Greg Luck
@version $Id: BlockingCache.java 796 2008-10-09 02:39:03Z gregluck $