ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/SequenceLock.java
Revision: 1.1
Committed: Fri Jul 15 13:14:47 2011 UTC (12 years, 11 months ago) by dl
Branch: MAIN
Log Message:
Initial commit of jdk8 targets

File Contents

# User Rev Content
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