Finally and catch
Read write locks
Lock
objects are used to control access to mutable data in a multithreaded environment.
When a thread is finished with the data, you must ensure the lock is released.
Brian Goetz in Java Concurrency in Practice strongly recommends the following technique for
ensuring that a lock is released. It uses a try..finally
style; this ensures that no matter what
happens during the time the lock is held, it will eventually be unlocked. Even if an unexpected
RuntimeException
is thrown, the lock will still be released.
Lock myLock = ... myLock.lock(); try { //interact with mutable data } finally{ myLock.unlock(); }
Here's an example which follows the above pattern, with a read-write lock.
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(); }