What is the proper number of stripes for Guava Striped?

Andrey Minogin :

I want to provide locking access to a resource using Guava Striped Lock. E.g.

Striped<Lock> keyLocks = Striped.lazyWeakLock(10)
Lock lock = keyLocks.get("resourceId")
// use lock...

I cannot find any guide how to choose the correct number of stripes for:

Striped.lazyWeakLock(int stripes)

Should stripes be bound to the number of processor cores or what?

Mikhail Kholodkov :

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).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=83947&siteId=1
Recommended