There's no a general rule of thumb, it depends on a trade-off between concurrency level and memory consumption. The Striped
JavaDoc partially explains it:
A striped Lock/Semaphore/ReadWriteLock
. This offers the underlying
lock striping similar to that of ConcurrentHashMap
in a reusable form,
and extends it for semaphores and read-write locks. Conceptually, lock
striping is the technique of dividing a lock into many stripes,
increasing the granularity of a single lock and allowing independent
operations to lock different stripes and proceed concurrently, instead
of creating contention for a single lock.
The guarantee provided by
this class is that equal keys lead to the same lock (or semaphore),
i.e. if key1.equals(key2)
then striped.get(key1) == striped.get(key2)
(assuming Object.hashCode()
is correctly implemented
for the keys). Note that if key1
is not equal to key2
, it is not
guaranteed that striped.get(key1) != striped.get(key2)
; the elements
might nevertheless be mapped to the same lock. The lower the number of
stripes, the higher the probability of this happening.
...
Prior to this class, one might be tempted to use Map<K, Lock>
, where K
represents the task. This maximizes concurrency by having each unique key mapped to a unique lock, but also maximizes memory footprint. On the other extreme, one could use a single lock for all tasks, which minimizes memory footprint but also minimizes concurrency. Instead of choosing either of these extremes, Striped
allows the user to trade between required concurrency and memory footprint. For example, if a set of tasks are CPU-bound, one could easily create a very compact Striped<Lock> of availableProcessors() * 4
stripes, instead of possibly thousands of locks which could be created in a Map<K, Lock>
structure.
In other words, Striped
provides a flexibility to select a number of locks, which are distributed between the keys, based on their hash code. This allows to dynamically apply a trade-off between concurrency and memory footprint, while retaining the key invariant that if key1.equals(key2)
, then striped.get(key1) == striped.get(key2)
.