Use finally to unlock
Occasionally, a class may benefit as well from a read-write lock, for exactly the same reasons - reads are much more frequent than writes. As usual, you should measure performance to determine if a read-write lock is really improving performance.
Here's a sketch of how to use such locks. It uses the
ReentrantReadWriteLock
of the java.util.concurrent
package.
import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** User preferences, using a read-write lock. <P>The context: preference information is read in upon startup. The config data is 'read-mostly': usually, a caller simply reads the information. It gets updated only occasionally. <P>Using a read-write lock means that multiple readers can access the same data simultaneously. If a single writer gets the lock, however, then all other callers (either reader or writer) will block until the lock is released by the writer. <P>(In practice, Brian Goetz reports that the implementation of ConcurrentHashMap is so good that it would likely suffice in many cases, instead of a read-write lock.) */ public final class Preferences { /** Fetch a setting - this is the more common operation. */ public String fetch(String name){ String result = ""; readLock.lock(); try { result = preferences.get(name); } finally { readLock.unlock(); } return result; } /** Change a setting - this is the less common operation. */ public void update(String name, String value){ writeLock.lock(); try { preferences.put(name, value); } finally { writeLock.unlock(); } } //...elided // PRIVATE /** Holds the preferences as simple name-value pairs of Strings. */ private final Map<String, String> preferences = new LinkedHashMap<>(); private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); }