1 |
package java.util.concurrent; |
2 |
|
3 |
/** |
4 |
* This class provides the most commonly useful implementation of a |
5 |
* {@link ReadWriteLock}. |
6 |
* |
7 |
* <p>This class has the following properties: |
8 |
* <ul> |
9 |
* <li><b>Acquisition order</b> |
10 |
* <p> This class does not impose a reader or writer preference |
11 |
* ordering for lock access. Instead, threads contend using an |
12 |
* approximately arrival-order policy. The actual order depends on the |
13 |
* order in which an internal {@link ReentrantLock} is granted, but |
14 |
* essentially when the write lock is released either the single writer |
15 |
* at the notional head of the queue will be assigned the write lock, or |
16 |
* the set of readers at the head of the queue will be assigned the read lock. |
17 |
* <p>If readers are active and a writer arrives then no subsequent readers |
18 |
* will be granted the read lock until after that writer has acquired and |
19 |
* released the write lock. |
20 |
* <p><b>Note:</b> As all threads, readers and writers, must pass through an |
21 |
* internal lock, it is possible for the read lock <tt>tryLock</tt> methods |
22 |
* to return <tt>false</tt> even if the lock is logically available to the |
23 |
* thread. |
24 |
* |
25 |
* <li><b>Reentrancy</b> |
26 |
* <p>This lock allows both readers and writers to reacquire read or |
27 |
* write locks in the style of a {@link ReentrantLock}. Readers are not |
28 |
* allowed until all write locks held by the writing thread have been |
29 |
* released. |
30 |
* <p>Additionally, a writer can acquire the read lock - but not vice-versa. |
31 |
* Among other applications, reentrancy can be useful when |
32 |
* write locks are held during calls or callbacks to methods that |
33 |
* perform reads under read locks. |
34 |
* If a reader tries to acquire the write lock it will never succeed. |
35 |
* |
36 |
* <li><b>Lock downgrading</b> |
37 |
* <p>Reentrancy also allows downgrading from the write lock to a read lock, |
38 |
* by acquiring the write lock, then the read lock and then releasing the |
39 |
* write lock. Note that upgrading, from a read lock to the write lock, is |
40 |
* <b>not</b> possible. |
41 |
* |
42 |
* <li><b>Interruption of lock aquisition</b> |
43 |
* <p>Both the read lock and write lock support interruption during lock |
44 |
* acquisition. |
45 |
* |
46 |
* <li><b>{@link Condition} support</b> |
47 |
* <p>The write lock provides a {@link Condition} implementation that |
48 |
* behaves in the same way, with respect to the write lock, as the |
49 |
* {@link Condition} implementation provided by |
50 |
* {@link ReentrantLock#newCondition} does for {@link ReentrantLock}. |
51 |
* This {@link Condition} can, of course, only be used with the write lock. |
52 |
* <p>The read lock does not support a {@link Condition} and |
53 |
* <tt>readLock().newCondition()</tt> will return <tt>null</tt>. |
54 |
* |
55 |
* <li><b>Ownership</b> |
56 |
* <p>While not exposing a means to query the owner, the write lock does |
57 |
* internally define an owner and so the write lock can only be released by |
58 |
* the thread that acquired it. |
59 |
* <p>In contrast, the read lock has no concept of ownership, simply a count |
60 |
* of the number of active readers. Consequently, while not a particularly |
61 |
* good practice, it is possible to acquire a read lock in one thread, and |
62 |
* release it in another. This can occasionally be useful. |
63 |
* |
64 |
* </ul> |
65 |
* |
66 |
* <p><b>Sample usage</b>. Here is a code sketch showing how to exploit |
67 |
* reentrancy to perform lock downgrading after updating a cache (exception |
68 |
* handling is elided for simplicity): |
69 |
* <pre> |
70 |
* class CachedData { |
71 |
* Object data; |
72 |
* volatile boolean cacheValid; |
73 |
* ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); |
74 |
* |
75 |
* void processCachedData() { |
76 |
* rwl.readLock().lock(); |
77 |
* if (!cacheValid) { |
78 |
* // upgrade lock manually |
79 |
* rwl.readLock().unlock(); // must unlock first to obtain writelock |
80 |
* rwl.writeLock().lock(); |
81 |
* if (!cacheValid) { // recheck |
82 |
* data = ... |
83 |
* cacheValid = true; |
84 |
* } |
85 |
* // downgrade lock |
86 |
* rwl.readLock().lock(); // reacquire read without giving up write lock |
87 |
* rwl.writeLock().unlock(); // unlock write, still hold read |
88 |
* } |
89 |
* |
90 |
* use(data); |
91 |
* rwl.readLock().unlock(); |
92 |
* } |
93 |
* } |
94 |
* </pre> |
95 |
* |
96 |
* @see ReentrantLock |
97 |
* @see Condition |
98 |
* @see ReadWriteLock |
99 |
* @see Locks |
100 |
* |
101 |
* @since 1.5 |
102 |
* @spec JSR-166 |
103 |
* @revised $Date: 2003/02/07 00:25:27 $ |
104 |
* @editor $Author: dholmes $ |
105 |
* |
106 |
*/ |
107 |
public class ReentrantReadWriteLock implements ReadWriteLock { |
108 |
|
109 |
public Lock readLock() { |
110 |
return null; |
111 |
} |
112 |
|
113 |
public Lock writeLock() { |
114 |
return null; |
115 |
} |
116 |
} |
117 |
|
118 |
|
119 |
|