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.
There are three flavors of this class: Striped<Lock>, Striped<Semaphore>, and
Striped<ReadWriteLock>. For each type, two implementations are offered: strong and weak Striped<Lock>, strong and weak Striped<Semaphore>, and strong and weak Striped<ReadWriteLock>. Strong means that all
stripes (locks/semaphores) are initialized eagerly, and are not reclaimed unless Striped
itself is reclaimable. Weak means that locks/semaphores are created lazily, and they are
allowed to be reclaimed if nobody is holding on to them. This is useful, for example, if one
wants to create a Striped<Lock> of many locks, but worries that in most cases only a
small portion of these would be in use.
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.
| Modifier and Type | Class and Description |
|---|---|
| private static class | Striped.CompactStriped<L>
Implementation of Striped where 2^k stripes are represented as an array of the same length, eagerly initialized. |
| pack-priv static class | Striped.LargeLazyStriped<L>
Implementation of Striped where up to 2^k stripes can be represented, using a ConcurrentMap where the key domain is [0..2^k). |
| private static class | |
| private static class | |
| private abstract static class | |
| pack-priv static class | Striped.SmallLazyStriped<L>
Implementation of Striped where up to 2^k stripes can be represented, using an AtomicReferenceArray of size 2^k. |
| private static class | Striped.WeakSafeCondition
Condition object that ensures a strong reference is retained to a specified object. |
| private static class | Striped.WeakSafeLock
Lock object that ensures a strong reference is retained to a specified object. |
| private static class | Striped.WeakSafeReadWriteLock
ReadWriteLock implementation whose read and write locks retain a reference back to this lock. |
| Modifier and Type | Field and Description |
|---|---|
| private static final int | ALL_SET
A bit mask were all bits are set. |
| private static final int | LARGE_LAZY_CUTOFF
If there are at least this many stripes, we assume the memory usage of a ConcurrentMap will be smaller than a large array. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public Iterable | Returns: the stripes corresponding to the objects (one per each object, derived by delegating toget(Object); may contain duplicates), in an increasing index order.arbitrary non-null keys keys)Returns the stripes that correspond to the passed objects, in ascending (as per |
| private static int | |
| pack-priv static <L> Striped | |
| public abstract L | |
| public abstract L | Returns: the stripe at the specified indexthe index of the stripe to return; must be in index)[0...size())Returns the stripe at the specified index. |
| pack-priv abstract int | |
| private static <L> Striped | |
| public static Striped | Returns: a newStriped<Lock>the minimum number of stripes (locks) required stripes)Creates a |
| public static Striped | Returns: a newStriped<ReadWriteLock>the minimum number of stripes (locks) required stripes)Creates a |
| public static Striped | Returns: a newStriped<Semaphore>the minimum number of stripes (semaphores) required stripes, int the number of permits in each semaphore permits)Creates a |
| public static Striped | Returns: a newStriped<Lock>the minimum number of stripes (locks) required stripes)Creates a |
| public static Striped | Returns: a newStriped<ReadWriteLock>the minimum number of stripes (locks) required stripes)Creates a |
| public static Striped | Returns: a newStriped<Semaphore>the minimum number of stripes (semaphores) required stripes, int the number of permits in each semaphore permits)Creates a |
| public abstract int | |
| private static int |
| ALL_SET | back to summary |
|---|---|
| private static final int ALL_SET A bit mask were all bits are set. | |
| LARGE_LAZY_CUTOFF | back to summary |
|---|---|
| private static final int LARGE_LAZY_CUTOFF If there are at least this many stripes, we assume the memory usage of a ConcurrentMap will be smaller than a large array. (This assumes that in the lazy case, most stripes are unused. As always, if many stripes are in use, a non-lazy striped makes more sense.) | |
| Striped | back to summary |
|---|---|
| private Striped() | |
| bulkGet | back to summary |
|---|---|
| public Iterable Returns the stripes that correspond to the passed objects, in ascending (as per It should be noted that using a
| |
| ceilToPowerOfTwo | back to summary |
|---|---|
| private static int ceilToPowerOfTwo(int x) | |
| custom | back to summary |
|---|---|
| pack-priv static <L> Striped Creates a | |
| get | back to summary |
|---|---|
| public abstract L get(Object key) Returns the stripe that corresponds to the passed key. It is always guaranteed that if
| |
| getAt | back to summary |
|---|---|
| public abstract L getAt(int index) Returns the stripe at the specified index. Valid indexes are 0, inclusively, to
| |
| indexFor | back to summary |
|---|---|
| pack-priv abstract int indexFor(Object key) Returns the index to which the given key is mapped, so that getAt(indexFor(key)) == get(key). | |
| lazy | back to summary |
|---|---|
| private static <L> Striped | |
| lazyWeakLock | back to summary |
|---|---|
| public static Striped Creates a | |
| lazyWeakReadWriteLock | back to summary |
|---|---|
| public static Striped Creates a
| |
| lazyWeakSemaphore | back to summary |
|---|---|
| public static Striped Creates a | |
| lock | back to summary |
|---|---|
| public static Striped Creates a | |
| readWriteLock | back to summary |
|---|---|
| public static Striped Creates a
| |
| semaphore | back to summary |
|---|---|
| public static Striped Creates a | |
| size | back to summary |
|---|---|
| public abstract int size() Returns the total number of stripes in this instance. | |
| smear | back to summary |
|---|---|
| private static int smear(int hashCode) | |
| Modifier and Type | Field and Description |
|---|---|
| private final Object[] | array
Size is a power of two. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public L | getAt(int
the index of the stripe to return; must be in index)[0...size())Implements abstract com. |
| public int | size()
Implements abstract com. |
| array | back to summary |
|---|---|
| private final Object[] array Size is a power of two. | |
| CompactStriped | back to summary |
|---|---|
| private CompactStriped(int stripes, Supplier<L> supplier) | |
| getAt | back to summary |
|---|---|
| public L getAt(int index) Implements abstract com. Doc from com. Returns the stripe at the specified index. Valid indexes are 0, inclusively, to
| |
| size | back to summary |
|---|---|
| public int size() Implements abstract com. Doc from com. Returns the total number of stripes in this instance.
| |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv final ConcurrentMap | |
| pack-priv final int | |
| pack-priv final Supplier |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| public L | getAt(int
the index of the stripe to return; must be in index)[0...size())Implements abstract com. |
| public int | size()
Implements abstract com. |
| locks | back to summary |
|---|---|
| pack-priv final ConcurrentMap<Integer, L> locks | |
| size | back to summary |
|---|---|
| pack-priv final int size | |
| supplier | back to summary |
|---|---|
| pack-priv final Supplier<L> supplier | |
| LargeLazyStriped | back to summary |
|---|---|
| pack-priv LargeLazyStriped(int stripes, Supplier<L> supplier) | |
| getAt | back to summary |
|---|---|
| public L getAt(int index) Implements abstract com. Doc from com. Returns the stripe at the specified index. Valid indexes are 0, inclusively, to
| |
| size | back to summary |
|---|---|
| public int size() Implements abstract com. Doc from com. Returns the total number of stripes in this instance.
| |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv long | |
| pack-priv long | |
| pack-priv long |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| unused1 | back to summary |
|---|---|
| pack-priv long unused1 | |
| unused2 | back to summary |
|---|---|
| pack-priv long unused2 | |
| unused3 | back to summary |
|---|---|
| pack-priv long unused3 | |
| PaddedLock | back to summary |
|---|---|
| pack-priv PaddedLock() | |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv long | |
| pack-priv long | |
| pack-priv long |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| unused1 | back to summary |
|---|---|
| pack-priv long unused1 | |
| unused2 | back to summary |
|---|---|
| pack-priv long unused2 | |
| unused3 | back to summary |
|---|---|
| pack-priv long unused3 | |
| PaddedSemaphore | back to summary |
|---|---|
| pack-priv PaddedSemaphore(int permits) | |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv final int | mask
Capacity (power of two) minus one, for fast mod evaluation |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| public final L | get(Object
an arbitrary, non-null key key)Implements abstract com. |
| pack-priv final int | indexFor(Object key)
Implements abstract com. |
| mask | back to summary |
|---|---|
| pack-priv final int mask Capacity (power of two) minus one, for fast mod evaluation | |
| PowerOfTwoStriped | back to summary |
|---|---|
| pack-priv PowerOfTwoStriped(int stripes) | |
| get | back to summary |
|---|---|
| public final L get(Object key) Implements abstract com. Doc from com. Returns the stripe that corresponds to the passed key. It is always guaranteed that if | |
| indexFor | back to summary |
|---|---|
| pack-priv final int indexFor(Object key) Implements abstract com. Doc from com. Returns the index to which the given key is mapped, so that getAt(indexFor(key)) == get(key).
| |
| Modifier and Type | Class and Description |
|---|---|
| private static class |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv final AtomicReferenceArray | |
| pack-priv final ReferenceQueue | |
| pack-priv final int | |
| pack-priv final Supplier |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| private void | |
| public L | getAt(int
the index of the stripe to return; must be in index)[0...size())Implements abstract com. |
| public int | size()
Implements abstract com. |
| locks | back to summary |
|---|---|
| pack-priv final AtomicReferenceArray<@Nullable Striped. | |
| queue | back to summary |
|---|---|
| pack-priv final ReferenceQueue<L> queue | |
| size | back to summary |
|---|---|
| pack-priv final int size | |
| supplier | back to summary |
|---|---|
| pack-priv final Supplier<L> supplier | |
| SmallLazyStriped | back to summary |
|---|---|
| pack-priv SmallLazyStriped(int stripes, Supplier<L> supplier) | |
| drainQueue | back to summary |
|---|---|
| private void drainQueue() | |
| getAt | back to summary |
|---|---|
| public L getAt(int index) Implements abstract com. Doc from com. Returns the stripe at the specified index. Valid indexes are 0, inclusively, to
| |
| size | back to summary |
|---|---|
| public int size() Implements abstract com. Doc from com. Returns the total number of stripes in this instance.
| |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv final int |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| index | back to summary |
|---|---|
| pack-priv final int index | |
| ArrayReference | back to summary |
|---|---|
| pack-priv ArrayReference(L referent, int index, ReferenceQueue<L> queue) | |
| Modifier and Type | Field and Description |
|---|---|
| private final Condition | |
| private final Striped. |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv Condition |
| delegate | back to summary |
|---|---|
| private final Condition delegate | |
| strongReference | back to summary |
|---|---|
private final Striped.
| |
| WeakSafeCondition | back to summary |
|---|---|
| pack-priv WeakSafeCondition(Condition delegate, Striped. | |
| delegate | back to summary |
|---|---|
| pack-priv Condition delegate() Implements abstract com.
| |
| Modifier and Type | Field and Description |
|---|---|
| private final Lock | |
| private final Striped. |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv Lock | |
| public Condition | newCondition()
Overrides com. Implements java. Condition instance that is bound to this
Lock instance.
|
| delegate | back to summary |
|---|---|
| private final Lock delegate | |
| strongReference | back to summary |
|---|---|
private final Striped.
| |
| WeakSafeLock | back to summary |
|---|---|
| pack-priv WeakSafeLock(Lock delegate, Striped. | |
| delegate | back to summary |
|---|---|
| pack-priv Lock delegate() Implements abstract com.
| |
| newCondition | back to summary |
|---|---|
| public Condition newCondition() Overrides com. Implements java. Doc from java. Returns a new Before waiting on the condition the lock must be held by the
current thread.
A call to Implementation Considerations The exact operation of the | |
ReadWriteLock is retained.
| Modifier and Type | Field and Description |
|---|---|
| private final ReadWriteLock |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| public Lock | readLock()
Implements java. |
| public Lock | writeLock()
Implements java. |
| delegate | back to summary |
|---|---|
| private final ReadWriteLock delegate | |
| WeakSafeReadWriteLock | back to summary |
|---|---|
| pack-priv WeakSafeReadWriteLock() | |
| readLock | back to summary |
|---|---|
| public Lock readLock() Implements java. Doc from java. Returns the lock used for reading. | |
| writeLock | back to summary |
|---|---|
| public Lock writeLock() Implements java. Doc from java. Returns the lock used for writing. | |