1 |
package java.util.concurrent; |
2 |
|
3 |
|
4 |
/** |
5 |
* Utility operations for built-in synchronization and {@link Lock} classes. |
6 |
* <p>The <tt>Locks</tt> class defines utility methods that enhance the |
7 |
* use of <tt>synchronized</tt> methods and statements by: |
8 |
* <ul> |
9 |
* <li>allowing for an attempt to acquire a monitor lock only if it is free, |
10 |
* or if it becomes free within a specified time; |
11 |
* <li>allowing an attempt to acquire a monitor lock to be interruptible; and |
12 |
* <li>providing a method to acquire multiple monitor locks only if |
13 |
* they are all available. |
14 |
* </ul> |
15 |
* <p>An additional convenience method is provided to acquire multiple |
16 |
* {@link Lock} instances only if they are all available. |
17 |
* <p>To preserve the block-structured locking that is required for the |
18 |
* built-in monitor locks, each method takes a {@link Runnable} action as |
19 |
* an argument and executes its {@link Runnable#run run} method with the |
20 |
* appropriate locks held. |
21 |
* When the {@link Runnable#run run} method completes all locks |
22 |
* are released. |
23 |
* |
24 |
* <p><b>Note:</b> All methods that take {@link Object} parameters treat |
25 |
* those parameters as {@link Object Objects}, even if they happen to be |
26 |
* {@link Lock} instances. These methods will always acquire the monitor |
27 |
* lock of the given object - they will not perform a {@link Lock#lock} |
28 |
* invocation. |
29 |
* |
30 |
* <p>Except where noted, passing a <tt>null</tt> value for any parameter |
31 |
* will result in a {@link NullPointerException} being thrown. |
32 |
* |
33 |
* <h3>Memory Synchronization</h3> |
34 |
* <p>When a {@link Runnable} object's {@link Runnable#run run} method is |
35 |
* executed it means that the appropriate |
36 |
* lock (or locks) has been acquired, and so the memory synchronization |
37 |
* effects of acquiring that lock will have taken place. Similarly, when |
38 |
* the {@link Runnable} object's {@link Runnable#run run} method completes, |
39 |
* the lock (or locks) is released and the associated memory synchronization |
40 |
* effects will take place. Exactly what those memory synchronization |
41 |
* effects are will depend on the nature of the lock and the type of |
42 |
* acquisition/release - for example, reentrantly acquiring a monitor lock |
43 |
* has no associated memory synchronization effects. |
44 |
* <p>When mutliple locks are involved it may be that some of the locks are |
45 |
* acquired and subsequently released, before an unavailable lock is found. |
46 |
* In that case the memory synchronization effects will be those of the locks |
47 |
* that were actually acquired and actually released. |
48 |
* |
49 |
* @since 1.5 |
50 |
* @spec JSR-166 |
51 |
* @revised $Date: 2003/01/09 17:56:51 $ |
52 |
* @editor $Author: dl $ |
53 |
* |
54 |
* @fixme add implementation notes for any performance issues related to |
55 |
* timeouts or interrupts |
56 |
**/ |
57 |
public class Locks { |
58 |
|
59 |
private Locks() {} // uninstantiable. |
60 |
|
61 |
/** |
62 |
* Performs the given action holding the monitor lock of |
63 |
* the given object only if that lock is currently free. |
64 |
* |
65 |
* <p>If the monitor lock of the given object is immediately available |
66 |
* to the current thread then it is acquired. |
67 |
* The action is then executed and finally the monitor lock is released |
68 |
* and the method returns with the value <tt>true</tt>. |
69 |
* <p>If the monitor lock is not available then the method returns |
70 |
* immediately with the value <tt>false</tt>. |
71 |
* <p>If the action completes abruptly due to an {@link Error} or |
72 |
* {@link RuntimeException}, then the method completes abruptly |
73 |
* for the same reason, after the lock has been released. |
74 |
* |
75 |
* @param lock the object whose monitor lock must be acquired |
76 |
* @param action the code to run while holding the monitor lock |
77 |
* @return <tt>true</tt> if the action was executed, and <tt>false</tt> |
78 |
* otherwise. |
79 |
**/ |
80 |
public static boolean attempt(Object lock, Runnable action) { |
81 |
return false; // for now; |
82 |
} |
83 |
|
84 |
/** |
85 |
* Performs the given action holding the monitor lock of |
86 |
* the given object if it is free within the given waiting time and the |
87 |
* current thread has not been {@link Thread#interrupt interrupted}. |
88 |
* |
89 |
* <p>If the monitor lock of the given object is immediately available |
90 |
* to the current thread then it is acquired. |
91 |
* The action is then executed and finally the monitor lock is released |
92 |
* and the method returns with the value <tt>true</tt>. |
93 |
* |
94 |
* <p>If the monitor lock is not available then |
95 |
* the current thread becomes disabled for thread scheduling |
96 |
* purposes and lies dormant until one of three things happens: |
97 |
* <ul> |
98 |
* <li> The monitor lock is acquired by the current thread; or |
99 |
* <li> Some other thread {@link Thread#interrupt interrupts} the current |
100 |
* thread; or |
101 |
* <li> The specified waiting time elapses |
102 |
* </ul> |
103 |
* <p>If the monitor lock is acquired |
104 |
* the action is executed then the monitor lock is released |
105 |
* and the method returns with the value <tt>true</tt>. |
106 |
* |
107 |
* <p>If the action completes abruptly due to an {@link Error} or |
108 |
* {@link RuntimeException}, then the method completes abruptly |
109 |
* for the same reason, after the lock has been released. |
110 |
* |
111 |
* <p>If the current thread: |
112 |
* <ul> |
113 |
* <li>has its interrupted status set on entry to this method; or |
114 |
* <li>is {@link Thread#interrupt interrupted} while waiting to acquire |
115 |
* the monitor lock, |
116 |
* </ul> |
117 |
* then {@link InterruptedException} is thrown and the current thread's |
118 |
* interrupted status is cleared. |
119 |
* |
120 |
* <p>If the specified waiting time elapses then the value <tt>false</tt> |
121 |
* is returned. |
122 |
* The given waiting time is a best-effort lower bound. If the time is |
123 |
* less than or equal to zero, the method will not wait at all. |
124 |
* |
125 |
* <p><b>Implementation Notes</b> |
126 |
* <p>TO-BE-DONE |
127 |
* |
128 |
* |
129 |
* @param lock the object whose monitor lock must be acquired |
130 |
* @param action the code to run while holding the monitor lock |
131 |
* @param timeout the maximum time to wait for the monitor lock |
132 |
* @param granularity the time unit of the <tt>timeout</tt> argument. |
133 |
* @return <tt>true</tt> if the monitor lock was acquired and the |
134 |
* action executed, and <tt>false</tt> |
135 |
* if the waiting time elapsed before the monitor lock was acquired. |
136 |
* |
137 |
* @throws InterruptedException if the current thread is interrupted |
138 |
* while trying to acquire the monitor lock. |
139 |
* |
140 |
* @see Thread#interrupt |
141 |
* |
142 |
**/ |
143 |
public static boolean attempt(Object lock, Runnable action, |
144 |
long timeout, TimeUnit granularity) |
145 |
throws InterruptedException { |
146 |
|
147 |
return false; // for now; |
148 |
} |
149 |
|
150 |
/** |
151 |
* Performs the given action holding the monitor locks of |
152 |
* the given objects only if those locks are currently free. |
153 |
* |
154 |
* <p>If the monitor locks of each object in the array are immediately |
155 |
* available to the current thread then they are acquired. |
156 |
* The action is then executed and finally the monitor locks are released |
157 |
* and the method returns with the value <tt>true</tt>. |
158 |
* <p>If any of the monitor locks is not available then |
159 |
* all previously acquired monitor locks are released and the method |
160 |
* returns with the value <tt>false</tt>. |
161 |
* <p>If the action completes abruptly due to an {@link Error} or |
162 |
* {@link RuntimeException}, then the method completes abruptly |
163 |
* for the same reason, after all the locks have been released. |
164 |
* |
165 |
* @param locks the objects whose monitor locks must be acquired |
166 |
* @param action the code to run while holding the monitor locks |
167 |
* @return <tt>true</tt> if the action was executed, and <tt>false</tt> |
168 |
* otherwise. |
169 |
* |
170 |
* @throws NullPointerException if an attempt is made to acquire the |
171 |
* monitor lock of a <tt>null</tt> element in the <tt>locks</tt> array. |
172 |
**/ |
173 |
public static boolean attempt(Object[] locks, Runnable action) { |
174 |
return false; // for now; |
175 |
} |
176 |
|
177 |
/** |
178 |
* Performs the given action holding the given {@link Lock} instances, only |
179 |
* if those {@link Lock} instances are currently free. |
180 |
* |
181 |
* <p>If each of the locks in the array are immediately |
182 |
* available to the current thread then they are acquired. |
183 |
* The action is then executed and finally the locks are |
184 |
* released and the method returns with the value <tt>true</tt>. |
185 |
* <p>If any of the locks are not available then |
186 |
* all previously acquired locks are released and the |
187 |
* method returns immediately with the value <tt>false</tt>. |
188 |
* <p>If the action completes abruptly due to an {@link Error} or |
189 |
* {@link RuntimeException}, then the method completes abruptly |
190 |
* for the same reason, after all the locks have been |
191 |
* released. |
192 |
* |
193 |
* @param locks the {@link Lock} instances that must be acquired |
194 |
* @param action the code to run while holding the given locks |
195 |
* @return <tt>true</tt> if the action was executed, and <tt>false</tt> |
196 |
* otherwise. |
197 |
* |
198 |
* @throws NullPointerException if an attempt is made to acquire the |
199 |
* lock of a <tt>null</tt> element in the <tt>locks</tt> array. |
200 |
**/ |
201 |
public static boolean attempt(Lock[] locks, Runnable action) { |
202 |
return false; // for now; |
203 |
} |
204 |
|
205 |
|
206 |
/** |
207 |
* Returns a {@link Condition} instance for use with the given object. |
208 |
* <p>The returned {@link Condition} instance has analagous behavior |
209 |
* to the use of the monitor methods on the given object. Given |
210 |
* <pre> Condition c = Locks.newConditionFor(o); |
211 |
* </pre> |
212 |
* then: |
213 |
* <ul> |
214 |
* <li><tt>c.await()</tt> is analagous to <tt>o.wait()</tt> |
215 |
* <li><tt>c.signal()</tt> is analagous to <tt>o.notify()</tt>; and |
216 |
* <li><tt>c.signalAll()</tt> is analagous to <tt>o.notifyAll()</tt> |
217 |
* </ul> |
218 |
* in that: |
219 |
* <ul> |
220 |
* <li>If the monitor lock of <tt>o</tt> is not held when any of the |
221 |
* {@link Condition} |
222 |
* {@link Condition#await() waiting} or {@link Condition#signal signalling} |
223 |
* methods are called, then an {@link IllegalMonitorStateException} is |
224 |
* thrown. |
225 |
* <li>When the condition {@link Condition#await() waiting} methods are |
226 |
* called the monitor lock of <tt>o</tt> is released and before they |
227 |
* return the monitor lock is |
228 |
* reacquired and the lock count restored to what it was when the |
229 |
* method was called. |
230 |
* <li>If a thread is {@link Thread#interrupt interrupted} while waiting |
231 |
* then the wait will terminate, an {@link InterruptedException} will be |
232 |
* thrown, and the thread's interrupted status will be cleared. |
233 |
* <li>The order in which waiting threads are signalled is not specified. |
234 |
* <li>The order in which threads returning from await, and threads trying |
235 |
* to acquire the monitor lock, are granted the lock, is not specified. |
236 |
* </ul> |
237 |
* <p>A {@link Condition} instance obtained in this way can be used to |
238 |
* create the |
239 |
* affect of having additional monitor wait-sets for the given object. |
240 |
* For example, suppose we have a bounded buffer which supports methods |
241 |
* to <tt>put</tt> and <tt>take</tt> items in/from the buffer. If a |
242 |
* <tt>take</tt> is attempted on an empty buffer then the thread will block |
243 |
* until an item becomes available; if a <tt>put</tt> is attempted on a |
244 |
* full buffer, then the thread will block until a space becomes available. |
245 |
* We would like to keep waiting <tt>put</tt> threads and <tt>take</tt> |
246 |
* threads in separate wait-sets so that we can use the optimisation of |
247 |
* only notifying a single thread at a time when items, or spaces, become |
248 |
* available in the buffer. This can be achieved using either two |
249 |
* {@link Condition} instances, or one {@link Condition} instance and the |
250 |
* actual |
251 |
* monitor wait-set. For clarity we'll use two {@link Condition} instances. |
252 |
* <pre><code> |
253 |
* class BoundedBuffer { |
254 |
* <b>final Condition notFull = Locks.newConditionFor(this); |
255 |
* final Condition notEmpty = Locks.newConditionFor(this); </b> |
256 |
* |
257 |
* Object[] items = new Object[100]; |
258 |
* int putptr, takeptr, count; |
259 |
* |
260 |
* public <b>synchronized</b> void put(Object x) |
261 |
* throws InterruptedException { |
262 |
* while (count == items.length) |
263 |
* <b>notFull.await();</b> |
264 |
* items[putptr] = x; |
265 |
* if (++putptr == items.length) putptr = 0; |
266 |
* ++count; |
267 |
* <b>notEmpty.signal();</b> |
268 |
* } |
269 |
* |
270 |
* public <b>synchronized</b> Object take() throws InterruptedException { |
271 |
* while (count == 0) |
272 |
* <b>notEmpty.await();</b> |
273 |
* Object x = items[takeptr]; |
274 |
* if (++takeptr == items.length) takeptr = 0; |
275 |
* --count; |
276 |
* <b>notFull.signal();</b> |
277 |
* return x; |
278 |
* } |
279 |
* } |
280 |
* </code></pre> |
281 |
* |
282 |
* @param lock the object that will be used for its monitor lock and to |
283 |
* which the returned condition should be bound. |
284 |
* @return a {@link Condition} instance bound to the given object |
285 |
**/ |
286 |
public static Condition newConditionFor(Object lock) { |
287 |
return null; // for now; |
288 |
} |
289 |
|
290 |
} |
291 |
|
292 |
|
293 |
|
294 |
|