I have a class that is accessed by multiple threads, and I want to make sure it's thread safe. Plus it needs to be as fast as possible. This is just an example:
public class SharedClass {
private final Map<String, String> data = new HashMap<>();
private final Striped<ReadWriteLock> rwLockStripes = Striped.readWriteLock(100);
public void setSomethingFastVersion(String key, String value) {
ReadWriteLock rwLock = rwLockStripes.get(key);
try {
rwLock.lock();
} finally{
rwLock.unLock();
}
data.put(key, value);
}
public synchronized void setSomethingSlowVersion(String key, String value) {
data.put(key, value);
}
}
I'm using StripedLock
from Google Guava in one version, and a normal synchronized
on the other one.
Am I right saying that the Guava version should be faster?
If so, what would be a good use case for synchronized
, where the StripedLocks
would not fit?
BTW, I know I could use a simple ConcurrentHashMap
here, but I'm adding the example code to make sure you understand my question.
Lock striping is a technique where the locking occurs on several buckets or stripes, meaning that accessing a bucket only locks that bucket and not the entire data structure.
What Is a Reentrant Lock? A reentrant lock is a mutual exclusion mechanism that allows threads to reenter into a lock on a resource (multiple times) without a deadlock situation. A thread entering into the lock increases the hold count by one every time. Similarly, the hold count decreases when unlock is requested.
A ReadWriteLock maintains a pair of associated locks , one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.
Synchronized has been around for ages. It's not really surprising that we nowadays have more advanced mechanisms for concurrent programming.
However striped locks are advantageous only in cases where something can be partitioned or striped, such as locking parts of a map allowing different parts to be manipulated at the same time, but blocking simultaneous manipulations to the same stripe. In many cases you don't have that kind of partitioning, you're just looking for a mutex. In those cases synchronized
is still a viable option, although a ReadWriteLock
might be a better choice depending on the situation.
A ConcurrentHashMap
has internal partitioning similar to stripes, but it applies only to the map operations such as put()
. With an explicit StripedLock
you can make longer operations atomic, while still allowing concurrency when operations don't touch the same stripe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With