1 |
dl |
1.1 |
/* |
2 |
|
|
* Written by Doug Lea with assistance from members of JCP JSR-166 |
3 |
|
|
* Expert Group and released to the public domain, as explained at |
4 |
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ |
5 |
|
|
*/ |
6 |
|
|
|
7 |
|
|
package jsr166e; |
8 |
|
|
import java.util.concurrent.TimeUnit; |
9 |
|
|
import java.util.concurrent.locks.Lock; |
10 |
|
|
import java.util.concurrent.locks.ReentrantLock; |
11 |
|
|
import java.util.concurrent.locks.Condition; |
12 |
|
|
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; |
13 |
|
|
import java.util.Collection; |
14 |
|
|
import java.io.ObjectOutputStream; |
15 |
|
|
import java.io.ObjectInputStream; |
16 |
|
|
import java.io.IOException; |
17 |
|
|
|
18 |
|
|
/** |
19 |
|
|
* A reentrant mutual exclusion {@link Lock} in which each lock |
20 |
|
|
* acquisition or release advances a sequence number. When the |
21 |
|
|
* sequence number (accessible using {@link #getSequence()}) is odd, |
22 |
|
|
* the lock is held. When it is even (i.e., {@code lock.getSequence() |
23 |
|
|
* & 1L) == 0L}), the lock is released. Method {@link |
24 |
|
|
* #awaitAvailability} can be used to await availability of the lock, |
25 |
|
|
* returning its current sequence number. Sequence numbers are of type |
26 |
|
|
* {@code long} to ensure that they will not wrap around until |
27 |
|
|
* hundreds of years of use under current processor rates. A |
28 |
|
|
* SequenceLock can be created with a specified number of |
29 |
|
|
* spins. Attempts to lock or await release retry at least the given |
30 |
|
|
* number of times before blocking. If not specified, a default, |
31 |
|
|
* possibly platform-specific, value is used. |
32 |
|
|
* |
33 |
|
|
* <p>Except for the lack of support for specified fairness policies, |
34 |
|
|
* a SequenceLock can be used in the same way as {@link |
35 |
|
|
* ReentrantLock}, and has a nearly identical API. SequenceLocks may |
36 |
|
|
* be preferable in contexts in which multiple threads invoke |
37 |
|
|
* read-only methods much more frequently than fully locked methods. |
38 |
|
|
* |
39 |
|
|
* <p> Methods {@code awaitAvailability} and {@code getSequence} can |
40 |
|
|
* be used together to define (partially) optimistic read-only methods |
41 |
|
|
* that are usually more efficient than ReadWriteLocks when they |
42 |
|
|
* apply. These read-only methods typically read multiple field |
43 |
|
|
* values into local variables when the lock is not held, retrying if |
44 |
|
|
* the sequence number changed while doing so. Alternatively, because |
45 |
|
|
* {@code awaitAvailability} accommodates reentrancy, a method can |
46 |
|
|
* retry a bounded number of times before switching to locking mode. |
47 |
|
|
* While conceptually straightforward, expressing these ideas can be |
48 |
|
|
* verbose. For example: |
49 |
|
|
* |
50 |
|
|
* <pre> {@code |
51 |
|
|
* class Point { |
52 |
|
|
* private float x, y; |
53 |
|
|
* private final SequenceLock sl = new SequenceLock(); |
54 |
|
|
* |
55 |
|
|
* void move(float deltaX, float deltaY) { // an excluively locked method |
56 |
|
|
* sl.lock(); |
57 |
|
|
* try { |
58 |
|
|
* x += deltaX; |
59 |
|
|
* y += deltaY; |
60 |
|
|
* } finally { |
61 |
|
|
* sl.unlock(); |
62 |
|
|
* } |
63 |
|
|
* } |
64 |
|
|
* |
65 |
|
|
* float distanceFromOriginV1() { // A read-only method |
66 |
|
|
* float currentX, currentY; |
67 |
|
|
* long seq; |
68 |
|
|
* do { |
69 |
|
|
* seq = sl.awaitAvailability(); |
70 |
|
|
* currentX = x; |
71 |
|
|
* currentY = y; |
72 |
|
|
* } while (sl.getSequence() != seq); // retry if sequence changed |
73 |
|
|
* return (float)Math.sqrt(currentX * currentX + currentY * currentY); |
74 |
|
|
* } |
75 |
|
|
* |
76 |
|
|
* float distanceFromOriginV2() { // Uses bounded retries before locking |
77 |
|
|
* float currentX, currentY; |
78 |
|
|
* long seq; |
79 |
|
|
* int retries = RETRIES_BEFORE_LOCKING; // for example 8 |
80 |
|
|
* try { |
81 |
|
|
* do { |
82 |
|
|
* if (--retries < 0) |
83 |
|
|
* sl.lock(); |
84 |
|
|
* seq = sl.awaitAvailability(); |
85 |
|
|
* currentX = x; |
86 |
|
|
* currentY = y; |
87 |
|
|
* } while (sl.getSequence() != seq); |
88 |
|
|
* } finally { |
89 |
|
|
* if (retries < 0) |
90 |
|
|
* sl.unlock(); |
91 |
|
|
* } |
92 |
|
|
* return (float)Math.sqrt(currentX * currentX + currentY * currentY); |
93 |
|
|
* } |
94 |
|
|
*}}</pre> |
95 |
|
|
* |
96 |
|
|
* @since 1.8 |
97 |
|
|
* @author Doug Lea |
98 |
|
|
*/ |
99 |
|
|
public class SequenceLock implements Lock, java.io.Serializable { |
100 |
|
|
private static final long serialVersionUID = 7373984872572414699L; |
101 |
|
|
|
102 |
|
|
static final class Sync extends AbstractQueuedLongSynchronizer { |
103 |
|
|
/** |
104 |
|
|
* The number of times to spin in lock() and awaitAvailability(). |
105 |
|
|
*/ |
106 |
|
|
final int spins; |
107 |
|
|
|
108 |
|
|
/** |
109 |
|
|
* The number of reentrant holds on this lock. Uses a long for |
110 |
|
|
* compatibility with other AbstractQueuedLongSynchronizer |
111 |
|
|
* operations. |
112 |
|
|
*/ |
113 |
|
|
long holds; |
114 |
|
|
|
115 |
|
|
Sync(int spins) { this.spins = spins; } |
116 |
|
|
|
117 |
|
|
// overrides of AQLS methods |
118 |
|
|
|
119 |
|
|
public final boolean isHeldExclusively() { |
120 |
|
|
return (getState() & 1L) != 0L && |
121 |
|
|
getExclusiveOwnerThread() == Thread.currentThread(); |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
public final boolean tryAcquire(long acquires) { |
125 |
|
|
Thread current = Thread.currentThread(); |
126 |
|
|
long c = getState(); |
127 |
|
|
if ((c & 1L) == 0L) { |
128 |
|
|
if (compareAndSetState(c, c + 1L)) { |
129 |
|
|
holds = acquires; |
130 |
|
|
setExclusiveOwnerThread(current); |
131 |
|
|
return true; |
132 |
|
|
} |
133 |
|
|
} |
134 |
|
|
else if (current == getExclusiveOwnerThread()) { |
135 |
|
|
holds += acquires; |
136 |
|
|
return true; |
137 |
|
|
} |
138 |
|
|
return false; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
public final boolean tryRelease(long releases) { |
142 |
|
|
if (Thread.currentThread() != getExclusiveOwnerThread()) |
143 |
|
|
throw new IllegalMonitorStateException(); |
144 |
|
|
if ((holds -= releases) == 0L) { |
145 |
|
|
setExclusiveOwnerThread(null); |
146 |
|
|
setState(getState() + 1L); |
147 |
|
|
return true; |
148 |
|
|
} |
149 |
|
|
return false; |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
public final long tryAcquireShared(long unused) { |
153 |
|
|
return ((getState() & 1L) == 0L || |
154 |
|
|
getExclusiveOwnerThread() == Thread.currentThread())? |
155 |
|
|
1L : -1L; // must return long |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
public final boolean tryReleaseShared(long unused) { |
159 |
|
|
return true; |
160 |
|
|
} |
161 |
|
|
|
162 |
|
|
public final Condition newCondition() { return new ConditionObject(); } |
163 |
|
|
|
164 |
|
|
// Other methods in support of SequenceLock |
165 |
|
|
|
166 |
|
|
final long getSequence() { |
167 |
|
|
return getState(); |
168 |
|
|
} |
169 |
|
|
|
170 |
|
|
final void lock() { |
171 |
|
|
int k = spins; |
172 |
|
|
while (!tryAcquire(1)) { |
173 |
|
|
if (k == 0) { |
174 |
|
|
acquire(1); |
175 |
|
|
break; |
176 |
|
|
} |
177 |
|
|
--k; |
178 |
|
|
} |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
final long awaitAvailability() { |
182 |
|
|
long s; |
183 |
|
|
int k = spins; |
184 |
|
|
while (((s = getState()) & 1L) != 0L && |
185 |
|
|
getExclusiveOwnerThread() != Thread.currentThread()) { |
186 |
|
|
if (k > 0) |
187 |
|
|
--k; |
188 |
|
|
else { |
189 |
|
|
acquireShared(1); |
190 |
|
|
releaseShared(1); |
191 |
|
|
} |
192 |
|
|
} |
193 |
|
|
return s; |
194 |
|
|
} |
195 |
|
|
|
196 |
|
|
final boolean isLocked() { |
197 |
|
|
return (getState() & 1L) != 0L; |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
final Thread getOwner() { |
201 |
|
|
return (getState() & 1L) != 0L ? null : getExclusiveOwnerThread(); |
202 |
|
|
} |
203 |
|
|
|
204 |
|
|
final long getHoldCount() { |
205 |
|
|
return isHeldExclusively()? holds : 0; |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
private void readObject(ObjectInputStream s) |
209 |
|
|
throws IOException, ClassNotFoundException { |
210 |
|
|
s.defaultReadObject(); |
211 |
|
|
holds = 0L; |
212 |
|
|
setState(0L); // reset to unlocked state |
213 |
|
|
} |
214 |
|
|
} |
215 |
|
|
|
216 |
|
|
private final Sync sync; |
217 |
|
|
|
218 |
|
|
/** |
219 |
|
|
* The default spin value for constructor. Future versions of this |
220 |
|
|
* class might choose platform-specific values. Currently, except |
221 |
|
|
* on uniprocessors, it is set to a small value that ovecomes near |
222 |
|
|
* misses between releases and acquires. |
223 |
|
|
*/ |
224 |
|
|
static final int DEFAULT_SPINS = |
225 |
|
|
Runtime.getRuntime().availableProcessors() > 1 ? 64 : 0; |
226 |
|
|
|
227 |
|
|
/** |
228 |
|
|
* Creates an instance of {@code SequenceLock} with the default |
229 |
|
|
* number of retry attempts to lock or await release before |
230 |
|
|
* blocking. |
231 |
|
|
*/ |
232 |
|
|
public SequenceLock() { sync = new Sync(DEFAULT_SPINS); } |
233 |
|
|
|
234 |
|
|
/** |
235 |
|
|
* Creates an instance of {@code SequenceLock} that |
236 |
|
|
* will retry attempts to lock or await release |
237 |
|
|
* at least the given number times before blocking. |
238 |
|
|
*/ |
239 |
|
|
public SequenceLock(int spins) { sync = new Sync(spins); } |
240 |
|
|
|
241 |
|
|
/** |
242 |
|
|
* Returns the current sequence number of this lock. The sequence |
243 |
|
|
* number is advanced upon each lock or unlock action. When this |
244 |
|
|
* value is odd, the lock is held; when even, it is released. |
245 |
|
|
* |
246 |
|
|
* @return the current sequence number |
247 |
|
|
*/ |
248 |
|
|
public long getSequence() { return sync.getSequence(); } |
249 |
|
|
|
250 |
|
|
/** |
251 |
|
|
* Returns the current sequence number when the lock is, or |
252 |
|
|
* becomes, available. A lock is available if it is either |
253 |
|
|
* released, or is held by the current thread. If the lock is not |
254 |
|
|
* available, the current thread becomes disabled for thread |
255 |
|
|
* scheduling purposes and lies dormant until the lock has been |
256 |
|
|
* released by some other thread. |
257 |
|
|
* |
258 |
|
|
* @return the current sequence number |
259 |
|
|
*/ |
260 |
|
|
public long awaitAvailability() { return sync.awaitAvailability(); } |
261 |
|
|
|
262 |
|
|
/** |
263 |
|
|
* Acquires the lock. |
264 |
|
|
* |
265 |
|
|
* <p>Acquires the lock if it is not held by another thread and returns |
266 |
|
|
* immediately, setting the lock hold count to one. |
267 |
|
|
* |
268 |
|
|
* <p>If the current thread already holds the lock then the hold |
269 |
|
|
* count is incremented by one and the method returns immediately. |
270 |
|
|
* |
271 |
|
|
* <p>If the lock is held by another thread then the |
272 |
|
|
* current thread becomes disabled for thread scheduling |
273 |
|
|
* purposes and lies dormant until the lock has been acquired, |
274 |
|
|
* at which time the lock hold count is set to one. |
275 |
|
|
*/ |
276 |
|
|
public void lock() { sync.lock(); } |
277 |
|
|
|
278 |
|
|
/** |
279 |
|
|
* Acquires the lock unless the current thread is |
280 |
|
|
* {@linkplain Thread#interrupt interrupted}. |
281 |
|
|
* |
282 |
|
|
* <p>Acquires the lock if it is not held by another thread and returns |
283 |
|
|
* immediately, setting the lock hold count to one. |
284 |
|
|
* |
285 |
|
|
* <p>If the current thread already holds this lock then the hold count |
286 |
|
|
* is incremented by one and the method returns immediately. |
287 |
|
|
* |
288 |
|
|
* <p>If the lock is held by another thread then the |
289 |
|
|
* current thread becomes disabled for thread scheduling |
290 |
|
|
* purposes and lies dormant until one of two things happens: |
291 |
|
|
* |
292 |
|
|
* <ul> |
293 |
|
|
* |
294 |
|
|
* <li>The lock is acquired by the current thread; or |
295 |
|
|
* |
296 |
|
|
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the |
297 |
|
|
* current thread. |
298 |
|
|
* |
299 |
|
|
* </ul> |
300 |
|
|
* |
301 |
|
|
* <p>If the lock is acquired by the current thread then the lock hold |
302 |
|
|
* count is set to one. |
303 |
|
|
* |
304 |
|
|
* <p>If the current thread: |
305 |
|
|
* |
306 |
|
|
* <ul> |
307 |
|
|
* |
308 |
|
|
* <li>has its interrupted status set on entry to this method; or |
309 |
|
|
* |
310 |
|
|
* <li>is {@linkplain Thread#interrupt interrupted} while acquiring |
311 |
|
|
* the lock, |
312 |
|
|
* |
313 |
|
|
* </ul> |
314 |
|
|
* |
315 |
|
|
* then {@link InterruptedException} is thrown and the current thread's |
316 |
|
|
* interrupted status is cleared. |
317 |
|
|
* |
318 |
|
|
* <p>In this implementation, as this method is an explicit |
319 |
|
|
* interruption point, preference is given to responding to the |
320 |
|
|
* interrupt over normal or reentrant acquisition of the lock. |
321 |
|
|
* |
322 |
|
|
* @throws InterruptedException if the current thread is interrupted |
323 |
|
|
*/ |
324 |
|
|
public void lockInterruptibly() throws InterruptedException { |
325 |
|
|
sync.acquireInterruptibly(1); |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
/** |
329 |
|
|
* Acquires the lock only if it is not held by another thread at the time |
330 |
|
|
* of invocation. |
331 |
|
|
* |
332 |
|
|
* <p>Acquires the lock if it is not held by another thread and |
333 |
|
|
* returns immediately with the value {@code true}, setting the |
334 |
|
|
* lock hold count to one. |
335 |
|
|
* |
336 |
|
|
* <p> If the current thread already holds this lock then the hold |
337 |
|
|
* count is incremented by one and the method returns {@code true}. |
338 |
|
|
* |
339 |
|
|
* <p>If the lock is held by another thread then this method will return |
340 |
|
|
* immediately with the value {@code false}. |
341 |
|
|
* |
342 |
|
|
* @return {@code true} if the lock was free and was acquired by the |
343 |
|
|
* current thread, or the lock was already held by the current |
344 |
|
|
* thread; and {@code false} otherwise |
345 |
|
|
*/ |
346 |
|
|
public boolean tryLock() { return sync.tryAcquire(1); } |
347 |
|
|
|
348 |
|
|
/** |
349 |
|
|
* Acquires the lock if it is not held by another thread within the given |
350 |
|
|
* waiting time and the current thread has not been |
351 |
|
|
* {@linkplain Thread#interrupt interrupted}. |
352 |
|
|
* |
353 |
|
|
* <p>Acquires the lock if it is not held by another thread and returns |
354 |
|
|
* immediately with the value {@code true}, setting the lock hold count |
355 |
|
|
* to one. If this lock has been set to use a fair ordering policy then |
356 |
|
|
* an available lock <em>will not</em> be acquired if any other threads |
357 |
|
|
* are waiting for the lock. This is in contrast to the {@link #tryLock()} |
358 |
|
|
* method. If you want a timed {@code tryLock} that does permit barging on |
359 |
|
|
* a fair lock then combine the timed and un-timed forms together: |
360 |
|
|
* |
361 |
|
|
* <pre> {@code |
362 |
|
|
* if (lock.tryLock() || |
363 |
|
|
* lock.tryLock(timeout, unit)) { |
364 |
|
|
* ... |
365 |
|
|
* }}</pre> |
366 |
|
|
* |
367 |
|
|
* <p>If the current thread |
368 |
|
|
* already holds this lock then the hold count is incremented by one and |
369 |
|
|
* the method returns {@code true}. |
370 |
|
|
* |
371 |
|
|
* <p>If the lock is held by another thread then the |
372 |
|
|
* current thread becomes disabled for thread scheduling |
373 |
|
|
* purposes and lies dormant until one of three things happens: |
374 |
|
|
* |
375 |
|
|
* <ul> |
376 |
|
|
* |
377 |
|
|
* <li>The lock is acquired by the current thread; or |
378 |
|
|
* |
379 |
|
|
* <li>Some other thread {@linkplain Thread#interrupt interrupts} |
380 |
|
|
* the current thread; or |
381 |
|
|
* |
382 |
|
|
* <li>The specified waiting time elapses |
383 |
|
|
* |
384 |
|
|
* </ul> |
385 |
|
|
* |
386 |
|
|
* <p>If the lock is acquired then the value {@code true} is returned and |
387 |
|
|
* the lock hold count is set to one. |
388 |
|
|
* |
389 |
|
|
* <p>If the current thread: |
390 |
|
|
* |
391 |
|
|
* <ul> |
392 |
|
|
* |
393 |
|
|
* <li>has its interrupted status set on entry to this method; or |
394 |
|
|
* |
395 |
|
|
* <li>is {@linkplain Thread#interrupt interrupted} while |
396 |
|
|
* acquiring the lock, |
397 |
|
|
* |
398 |
|
|
* </ul> |
399 |
|
|
* then {@link InterruptedException} is thrown and the current thread's |
400 |
|
|
* interrupted status is cleared. |
401 |
|
|
* |
402 |
|
|
* <p>If the specified waiting time elapses then the value {@code false} |
403 |
|
|
* is returned. If the time is less than or equal to zero, the method |
404 |
|
|
* will not wait at all. |
405 |
|
|
* |
406 |
|
|
* <p>In this implementation, as this method is an explicit |
407 |
|
|
* interruption point, preference is given to responding to the |
408 |
|
|
* interrupt over normal or reentrant acquisition of the lock, and |
409 |
|
|
* over reporting the elapse of the waiting time. |
410 |
|
|
* |
411 |
|
|
* @param timeout the time to wait for the lock |
412 |
|
|
* @param unit the time unit of the timeout argument |
413 |
|
|
* @return {@code true} if the lock was free and was acquired by the |
414 |
|
|
* current thread, or the lock was already held by the current |
415 |
|
|
* thread; and {@code false} if the waiting time elapsed before |
416 |
|
|
* the lock could be acquired |
417 |
|
|
* @throws InterruptedException if the current thread is interrupted |
418 |
|
|
* @throws NullPointerException if the time unit is null |
419 |
|
|
* |
420 |
|
|
*/ |
421 |
|
|
public boolean tryLock(long timeout, TimeUnit unit) |
422 |
|
|
throws InterruptedException { |
423 |
|
|
return sync.tryAcquireNanos(1, unit.toNanos(timeout)); |
424 |
|
|
} |
425 |
|
|
|
426 |
|
|
/** |
427 |
|
|
* Attempts to release this lock. |
428 |
|
|
* |
429 |
|
|
* <p>If the current thread is the holder of this lock then the hold |
430 |
|
|
* count is decremented. If the hold count is now zero then the lock |
431 |
|
|
* is released. If the current thread is not the holder of this |
432 |
|
|
* lock then {@link IllegalMonitorStateException} is thrown. |
433 |
|
|
* |
434 |
|
|
* @throws IllegalMonitorStateException if the current thread does not |
435 |
|
|
* hold this lock |
436 |
|
|
*/ |
437 |
|
|
public void unlock() { sync.release(1); } |
438 |
|
|
|
439 |
|
|
/** |
440 |
|
|
* Returns a {@link Condition} instance for use with this |
441 |
|
|
* {@link Lock} instance. |
442 |
|
|
* |
443 |
|
|
* <p>The returned {@link Condition} instance supports the same |
444 |
|
|
* usages as do the {@link Object} monitor methods ({@link |
445 |
|
|
* Object#wait() wait}, {@link Object#notify notify}, and {@link |
446 |
|
|
* Object#notifyAll notifyAll}) when used with the built-in |
447 |
|
|
* monitor lock. |
448 |
|
|
* |
449 |
|
|
* <ul> |
450 |
|
|
* |
451 |
|
|
* <li>If this lock is not held when any of the {@link Condition} |
452 |
|
|
* {@linkplain Condition#await() waiting} or {@linkplain |
453 |
|
|
* Condition#signal signalling} methods are called, then an {@link |
454 |
|
|
* IllegalMonitorStateException} is thrown. |
455 |
|
|
* |
456 |
|
|
* <li>When the condition {@linkplain Condition#await() waiting} |
457 |
|
|
* methods are called the lock is released and, before they |
458 |
|
|
* return, the lock is reacquired and the lock hold count restored |
459 |
|
|
* to what it was when the method was called. |
460 |
|
|
* |
461 |
|
|
* <li>If a thread is {@linkplain Thread#interrupt interrupted} |
462 |
|
|
* while waiting then the wait will terminate, an {@link |
463 |
|
|
* InterruptedException} will be thrown, and the thread's |
464 |
|
|
* interrupted status will be cleared. |
465 |
|
|
* |
466 |
|
|
* <li> Waiting threads are signalled in FIFO order. |
467 |
|
|
* |
468 |
|
|
* <li>The ordering of lock reacquisition for threads returning |
469 |
|
|
* from waiting methods is the same as for threads initially |
470 |
|
|
* acquiring the lock. |
471 |
|
|
* </ul> |
472 |
|
|
* |
473 |
|
|
* @return the Condition object |
474 |
|
|
*/ |
475 |
|
|
public Condition newCondition() { return sync.newCondition(); } |
476 |
|
|
|
477 |
|
|
/** |
478 |
|
|
* Queries the number of holds on this lock by the current thread. |
479 |
|
|
* |
480 |
|
|
* <p>A thread has a hold on a lock for each lock action that is not |
481 |
|
|
* matched by an unlock action. |
482 |
|
|
* |
483 |
|
|
* <p>The hold count information is typically only used for testing and |
484 |
|
|
* debugging purposes. |
485 |
|
|
* |
486 |
|
|
* @return the number of holds on this lock by the current thread, |
487 |
|
|
* or zero if this lock is not held by the current thread |
488 |
|
|
*/ |
489 |
|
|
public long getHoldCount() { return sync.getHoldCount(); } |
490 |
|
|
|
491 |
|
|
/** |
492 |
|
|
* Queries if this lock is held by the current thread. |
493 |
|
|
* |
494 |
|
|
* @return {@code true} if current thread holds this lock and |
495 |
|
|
* {@code false} otherwise |
496 |
|
|
*/ |
497 |
|
|
public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } |
498 |
|
|
|
499 |
|
|
/** |
500 |
|
|
* Queries if this lock is held by any thread. This method is |
501 |
|
|
* designed for use in monitoring of the system state, |
502 |
|
|
* not for synchronization control. |
503 |
|
|
* |
504 |
|
|
* @return {@code true} if any thread holds this lock and |
505 |
|
|
* {@code false} otherwise |
506 |
|
|
*/ |
507 |
|
|
public boolean isLocked() { return sync.isLocked(); } |
508 |
|
|
|
509 |
|
|
/** |
510 |
|
|
* Returns the thread that currently owns this lock, or |
511 |
|
|
* {@code null} if not owned. When this method is called by a |
512 |
|
|
* thread that is not the owner, the return value reflects a |
513 |
|
|
* best-effort approximation of current lock status. For example, |
514 |
|
|
* the owner may be momentarily {@code null} even if there are |
515 |
|
|
* threads trying to acquire the lock but have not yet done so. |
516 |
|
|
* This method is designed to facilitate construction of |
517 |
|
|
* subclasses that provide more extensive lock monitoring |
518 |
|
|
* facilities. |
519 |
|
|
* |
520 |
|
|
* @return the owner, or {@code null} if not owned |
521 |
|
|
*/ |
522 |
|
|
protected Thread getOwner() { return sync.getOwner(); } |
523 |
|
|
|
524 |
|
|
/** |
525 |
|
|
* Queries whether any threads are waiting to acquire this lock. Note that |
526 |
|
|
* because cancellations may occur at any time, a {@code true} |
527 |
|
|
* return does not guarantee that any other thread will ever |
528 |
|
|
* acquire this lock. This method is designed primarily for use in |
529 |
|
|
* monitoring of the system state. |
530 |
|
|
* |
531 |
|
|
* @return {@code true} if there may be other threads waiting to |
532 |
|
|
* acquire the lock |
533 |
|
|
*/ |
534 |
|
|
public final boolean hasQueuedThreads() { |
535 |
|
|
return sync.hasQueuedThreads(); |
536 |
|
|
} |
537 |
|
|
|
538 |
|
|
/** |
539 |
|
|
* Queries whether the given thread is waiting to acquire this |
540 |
|
|
* lock. Note that because cancellations may occur at any time, a |
541 |
|
|
* {@code true} return does not guarantee that this thread |
542 |
|
|
* will ever acquire this lock. This method is designed primarily for use |
543 |
|
|
* in monitoring of the system state. |
544 |
|
|
* |
545 |
|
|
* @param thread the thread |
546 |
|
|
* @return {@code true} if the given thread is queued waiting for this lock |
547 |
|
|
* @throws NullPointerException if the thread is null |
548 |
|
|
*/ |
549 |
|
|
public final boolean hasQueuedThread(Thread thread) { |
550 |
|
|
return sync.isQueued(thread); |
551 |
|
|
} |
552 |
|
|
|
553 |
|
|
/** |
554 |
|
|
* Returns an estimate of the number of threads waiting to |
555 |
|
|
* acquire this lock. The value is only an estimate because the number of |
556 |
|
|
* threads may change dynamically while this method traverses |
557 |
|
|
* internal data structures. This method is designed for use in |
558 |
|
|
* monitoring of the system state, not for synchronization |
559 |
|
|
* control. |
560 |
|
|
* |
561 |
|
|
* @return the estimated number of threads waiting for this lock |
562 |
|
|
*/ |
563 |
|
|
public final int getQueueLength() { |
564 |
|
|
return sync.getQueueLength(); |
565 |
|
|
} |
566 |
|
|
|
567 |
|
|
/** |
568 |
|
|
* Returns a collection containing threads that may be waiting to |
569 |
|
|
* acquire this lock. Because the actual set of threads may change |
570 |
|
|
* dynamically while constructing this result, the returned |
571 |
|
|
* collection is only a best-effort estimate. The elements of the |
572 |
|
|
* returned collection are in no particular order. This method is |
573 |
|
|
* designed to facilitate construction of subclasses that provide |
574 |
|
|
* more extensive monitoring facilities. |
575 |
|
|
* |
576 |
|
|
* @return the collection of threads |
577 |
|
|
*/ |
578 |
|
|
protected Collection<Thread> getQueuedThreads() { |
579 |
|
|
return sync.getQueuedThreads(); |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
/** |
583 |
|
|
* Queries whether any threads are waiting on the given condition |
584 |
|
|
* associated with this lock. Note that because timeouts and |
585 |
|
|
* interrupts may occur at any time, a {@code true} return does |
586 |
|
|
* not guarantee that a future {@code signal} will awaken any |
587 |
|
|
* threads. This method is designed primarily for use in |
588 |
|
|
* monitoring of the system state. |
589 |
|
|
* |
590 |
|
|
* @param condition the condition |
591 |
|
|
* @return {@code true} if there are any waiting threads |
592 |
|
|
* @throws IllegalMonitorStateException if this lock is not held |
593 |
|
|
* @throws IllegalArgumentException if the given condition is |
594 |
|
|
* not associated with this lock |
595 |
|
|
* @throws NullPointerException if the condition is null |
596 |
|
|
*/ |
597 |
|
|
public boolean hasWaiters(Condition condition) { |
598 |
|
|
if (condition == null) |
599 |
|
|
throw new NullPointerException(); |
600 |
|
|
if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) |
601 |
|
|
throw new IllegalArgumentException("not owner"); |
602 |
|
|
return sync.hasWaiters((AbstractQueuedLongSynchronizer.ConditionObject)condition); |
603 |
|
|
} |
604 |
|
|
|
605 |
|
|
/** |
606 |
|
|
* Returns an estimate of the number of threads waiting on the |
607 |
|
|
* given condition associated with this lock. Note that because |
608 |
|
|
* timeouts and interrupts may occur at any time, the estimate |
609 |
|
|
* serves only as an upper bound on the actual number of waiters. |
610 |
|
|
* This method is designed for use in monitoring of the system |
611 |
|
|
* state, not for synchronization control. |
612 |
|
|
* |
613 |
|
|
* @param condition the condition |
614 |
|
|
* @return the estimated number of waiting threads |
615 |
|
|
* @throws IllegalMonitorStateException if this lock is not held |
616 |
|
|
* @throws IllegalArgumentException if the given condition is |
617 |
|
|
* not associated with this lock |
618 |
|
|
* @throws NullPointerException if the condition is null |
619 |
|
|
*/ |
620 |
|
|
public int getWaitQueueLength(Condition condition) { |
621 |
|
|
if (condition == null) |
622 |
|
|
throw new NullPointerException(); |
623 |
|
|
if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) |
624 |
|
|
throw new IllegalArgumentException("not owner"); |
625 |
|
|
return sync.getWaitQueueLength((AbstractQueuedLongSynchronizer.ConditionObject)condition); |
626 |
|
|
} |
627 |
|
|
|
628 |
|
|
/** |
629 |
|
|
* Returns a collection containing those threads that may be |
630 |
|
|
* waiting on the given condition associated with this lock. |
631 |
|
|
* Because the actual set of threads may change dynamically while |
632 |
|
|
* constructing this result, the returned collection is only a |
633 |
|
|
* best-effort estimate. The elements of the returned collection |
634 |
|
|
* are in no particular order. This method is designed to |
635 |
|
|
* facilitate construction of subclasses that provide more |
636 |
|
|
* extensive condition monitoring facilities. |
637 |
|
|
* |
638 |
|
|
* @param condition the condition |
639 |
|
|
* @return the collection of threads |
640 |
|
|
* @throws IllegalMonitorStateException if this lock is not held |
641 |
|
|
* @throws IllegalArgumentException if the given condition is |
642 |
|
|
* not associated with this lock |
643 |
|
|
* @throws NullPointerException if the condition is null |
644 |
|
|
*/ |
645 |
|
|
protected Collection<Thread> getWaitingThreads(Condition condition) { |
646 |
|
|
if (condition == null) |
647 |
|
|
throw new NullPointerException(); |
648 |
|
|
if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) |
649 |
|
|
throw new IllegalArgumentException("not owner"); |
650 |
|
|
return sync.getWaitingThreads((AbstractQueuedLongSynchronizer.ConditionObject)condition); |
651 |
|
|
} |
652 |
|
|
|
653 |
|
|
/** |
654 |
|
|
* Returns a string identifying this lock, as well as its lock state. |
655 |
|
|
* The state, in brackets, includes either the String {@code "Unlocked"} |
656 |
|
|
* or the String {@code "Locked by"} followed by the |
657 |
|
|
* {@linkplain Thread#getName name} of the owning thread. |
658 |
|
|
* |
659 |
|
|
* @return a string identifying this lock, as well as its lock state |
660 |
|
|
*/ |
661 |
|
|
public String toString() { |
662 |
|
|
Thread o = sync.getOwner(); |
663 |
|
|
return super.toString() + ((o == null) ? |
664 |
|
|
"[Unlocked]" : |
665 |
|
|
"[Locked by thread " + o.getName() + "]"); |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
} |
669 |
|
|
|