ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/SequenceLock.java
(Generate patch)

Comparing jsr166/src/jsr166e/SequenceLock.java (file contents):
Revision 1.1 by dl, Fri Jul 15 13:14:47 2011 UTC vs.
Revision 1.10 by dl, Thu Jul 21 12:49:33 2011 UTC

# Line 6 | Line 6
6  
7   package jsr166e;
8   import java.util.concurrent.TimeUnit;
9 + import java.util.concurrent.TimeoutException;
10   import java.util.concurrent.locks.Lock;
11   import java.util.concurrent.locks.ReentrantLock;
12   import java.util.concurrent.locks.Condition;
# Line 19 | Line 20 | import java.io.IOException;
20   * A reentrant mutual exclusion {@link Lock} in which each lock
21   * acquisition or release advances a sequence number.  When the
22   * sequence number (accessible using {@link #getSequence()}) is odd,
23 < * the lock is held. When it is even (i.e., {@code lock.getSequence()
23 > * the lock is held. When it is even (i.e., ({@code lock.getSequence()
24   * & 1L) == 0L}), the lock is released. Method {@link
25   * #awaitAvailability} can be used to await availability of the lock,
26 < * returning its current sequence number. Sequence numbers are of type
27 < * {@code long} to ensure that they will not wrap around until
28 < * hundreds of years of use under current processor rates.  A
29 < * SequenceLock can be created with a specified number of
30 < * spins. Attempts to lock or await release retry at least the given
31 < * number of times before blocking. If not specified, a default,
32 < * possibly platform-specific, value is used.
26 > * returning its current sequence number. Sequence numbers (as well as
27 > * reentrant hold counts) are of type {@code long} to ensure that they
28 > * will not wrap around until hundreds of years of use under current
29 > * processor rates.  A SequenceLock can be created with a specified
30 > * number of spins. Attempts to acquire the lock in method {@link
31 > * #lock} will retry at least the given number of times before
32 > * blocking. If not specified, a default, possibly platform-specific,
33 > * value is used.
34   *
35   * <p>Except for the lack of support for specified fairness policies,
36 < * a SequenceLock can be used in the same way as {@link
37 < * ReentrantLock}, and has a nearly identical API. SequenceLocks may
38 < * be preferable in contexts in which multiple threads invoke
39 < * read-only methods much more frequently than fully locked methods.
40 < *
36 > * or {@link Condition} objects, a SequenceLock can be used in the
37 > * same way as {@link ReentrantLock}. It provides similar status and
38 > * monitoring methods such as {@link #isHeldByCurrentThread}.
39 > * SequenceLocks may be preferable in contexts in which multiple
40 > * threads invoke short read-only methods much more frequently than
41 > * fully locked methods.
42 > *
43   * <p> Methods {@code awaitAvailability} and {@code getSequence} can
44   * be used together to define (partially) optimistic read-only methods
45   * that are usually more efficient than ReadWriteLocks when they
46 < * apply.  These read-only methods typically read multiple field
47 < * values into local variables when the lock is not held, retrying if
48 < * the sequence number changed while doing so.  Alternatively, because
49 < * {@code awaitAvailability} accommodates reentrancy, a method can
50 < * retry a bounded number of times before switching to locking mode.
51 < * While conceptually straightforward, expressing these ideas can be
52 < * verbose. For example:
46 > * apply.  These methods should in general be structured as loops that
47 > * await lock availablity, then read {@code volatile} fields into
48 > * local variables (and may further read other values derived from
49 > * these, for example the {@code length} of a {@code volatile} array),
50 > * and retry if the sequence number changed while doing so.
51 > * Alternatively, because {@code awaitAvailability} accommodates
52 > * reentrancy, a method can retry a bounded number of times before
53 > * switching to locking mode.  While conceptually straightforward,
54 > * expressing these ideas can be verbose. For example:
55   *
56   * <pre> {@code
57   * class Point {
58 < *     private float x, y;
58 > *     private volatile double x, y;
59   *     private final SequenceLock sl = new SequenceLock();
60   *
61 < *     void move(float deltaX, float deltaY) { // an excluively locked method
61 > *     void move(double deltaX, double deltaY) { // an exclusively locked method
62   *        sl.lock();
63   *        try {
64   *            x += deltaX;
# Line 62 | Line 68 | import java.io.IOException;
68   *      }
69   *  }
70   *
71 < *  float distanceFromOriginV1() { // A read-only method
72 < *      float currentX, currentY;
71 > *  double distanceFromOriginV1() { // A read-only method
72 > *      double currentX, currentY;
73   *      long seq;
74   *      do {
75   *          seq = sl.awaitAvailability();
76   *          currentX = x;
77   *          currentY = y;
78   *      } while (sl.getSequence() != seq); // retry if sequence changed
79 < *      return (float)Math.sqrt(currentX * currentX + currentY * currentY);
79 > *      return Math.sqrt(currentX * currentX + currentY * currentY);
80   *  }
81   *
82 < *  float distanceFromOriginV2() { // Uses bounded retries before locking
83 < *      float currentX, currentY;
82 > *  double distanceFromOriginV2() { // Uses bounded retries before locking
83 > *      double currentX, currentY;
84   *      long seq;
85   *      int retries = RETRIES_BEFORE_LOCKING; // for example 8
86   *      try {
# Line 89 | Line 95 | import java.io.IOException;
95   *        if (retries < 0)
96   *           sl.unlock();
97   *      }
98 < *      return (float)Math.sqrt(currentX * currentX + currentY * currentY);
98 > *      return Math.sqrt(currentX * currentX + currentY * currentY);
99   *  }
100   *}}</pre>
101   *
# Line 108 | Line 114 | public class SequenceLock implements Loc
114          /**
115           * The number of reentrant holds on this lock. Uses a long for
116           * compatibility with other AbstractQueuedLongSynchronizer
117 <         * operations.
117 >         * operations. Accessed only by lock holder.
118           */
119          long holds;
120  
# Line 120 | Line 126 | public class SequenceLock implements Loc
126              return (getState() & 1L) != 0L &&
127                  getExclusiveOwnerThread() == Thread.currentThread();
128          }
129 <        
129 >
130          public final boolean tryAcquire(long acquires) {
131              Thread current = Thread.currentThread();
132              long c = getState();
# Line 137 | Line 143 | public class SequenceLock implements Loc
143              }
144              return false;
145          }
146 <        
146 >
147          public final boolean tryRelease(long releases) {
148              if (Thread.currentThread() != getExclusiveOwnerThread())
149                  throw new IllegalMonitorStateException();
# Line 150 | Line 156 | public class SequenceLock implements Loc
156          }
157  
158          public final long tryAcquireShared(long unused) {
159 <            return ((getState() & 1L) == 0L ||
160 <                    getExclusiveOwnerThread() == Thread.currentThread())?
161 <                1L : -1L; // must return long
159 >            return (((getState() & 1L) == 0L) ? 1L :
160 >                    (getExclusiveOwnerThread() == Thread.currentThread()) ?  0L:
161 >                    -1L);
162          }
163  
164          public final boolean tryReleaseShared(long unused) {
165 <            return true;
165 >            return (getState() & 1L) == 0L;
166          }
167  
168 <        public final Condition newCondition() { return new ConditionObject(); }
168 >        public final Condition newCondition() {
169 >            throw new UnsupportedOperationException();
170 >        }
171  
172          // Other methods in support of SequenceLock
173  
174          final long getSequence() {
175              return getState();
176          }
177 <        
177 >
178          final void lock() {
179              int k = spins;
180 <            while (!tryAcquire(1)) {
180 >            while (!tryAcquire(1L)) {
181                  if (k == 0) {
182 <                    acquire(1);
182 >                    acquire(1L);
183                      break;
184                  }
185                  --k;
186              }
187          }
188 <        
188 >
189          final long awaitAvailability() {
190              long s;
183            int k = spins;
191              while (((s = getState()) & 1L) != 0L &&
192                     getExclusiveOwnerThread() != Thread.currentThread()) {
193 <                if (k > 0)
194 <                    --k;
188 <                else {
189 <                    acquireShared(1);
190 <                    releaseShared(1);
191 <                }
193 >                acquireShared(1L);
194 >                releaseShared(1L);
195              }
196              return s;
197          }
198  
199 +        final long tryAwaitAvailability(long nanos)
200 +            throws InterruptedException, TimeoutException {
201 +            Thread current = Thread.currentThread();
202 +            for (;;) {
203 +                long s = getState();
204 +                if ((s & 1L) == 0L || getExclusiveOwnerThread() == current) {
205 +                    releaseShared(1L);
206 +                    return s;
207 +                }
208 +                if (!tryAcquireSharedNanos(1L, nanos))
209 +                    throw new TimeoutException();
210 +                // since tryAcquireSharedNanos doesn't return seq
211 +                // retry with minimal wait time.
212 +                nanos = 1L;
213 +            }
214 +        }
215 +
216          final boolean isLocked() {
217              return (getState() & 1L) != 0L;
218          }
219  
220          final Thread getOwner() {
221 <            return (getState() & 1L) != 0L ? null : getExclusiveOwnerThread();
221 >            return (getState() & 1L) == 0L ? null : getExclusiveOwnerThread();
222          }
223  
224          final long getHoldCount() {
225 <            return isHeldExclusively()? holds : 0;
225 >            return isHeldExclusively() ? holds : 0;
226          }
227  
228          private void readObject(ObjectInputStream s)
# Line 215 | Line 235 | public class SequenceLock implements Loc
235  
236      private final Sync sync;
237  
238 <    /**
238 >    /**
239       * The default spin value for constructor. Future versions of this
240       * class might choose platform-specific values.  Currently, except
241 <     * on uniprocessors, it is set to a small value that ovecomes near
241 >     * on uniprocessors, it is set to a small value that overcomes near
242       * misses between releases and acquires.
243       */
244 <    static final int DEFAULT_SPINS =
244 >    static final int DEFAULT_SPINS =
245          Runtime.getRuntime().availableProcessors() > 1 ? 64 : 0;
246  
247      /**
248       * Creates an instance of {@code SequenceLock} with the default
249 <     * number of retry attempts to lock or await release before
230 <     * blocking.
249 >     * number of retry attempts to acquire the lock before blocking.
250       */
251      public SequenceLock() { sync = new Sync(DEFAULT_SPINS); }
252  
253      /**
254 <     * Creates an instance of {@code SequenceLock} that
255 <     * will retry attempts to lock or await release
256 <     * at least the given number times before blocking.
254 >     * Creates an instance of {@code SequenceLock} that will retry
255 >     * attempts to acquire the lock at least the given number times
256 >     * before blocking.
257       */
258      public SequenceLock(int spins) { sync = new Sync(spins); }
259  
260      /**
261       * Returns the current sequence number of this lock.  The sequence
262 <     * number is advanced upon each lock or unlock action. When this
263 <     * value is odd, the lock is held; when even, it is released.
262 >     * number is advanced upon each acquire or release action. When
263 >     * this value is odd, the lock is held; when even, it is released.
264       *
265       * @return the current sequence number
266       */
# Line 258 | Line 277 | public class SequenceLock implements Loc
277       * @return the current sequence number
278       */
279      public long awaitAvailability() { return sync.awaitAvailability(); }
280 <    
280 >
281      /**
282 <     * Acquires the lock.
282 >     * Returns the current sequence number if the lock is, or
283 >     * becomes, available within the specified waiting time.
284       *
285 <     * <p>Acquires the lock if it is not held by another thread and returns
286 <     * immediately, setting the lock hold count to one.
285 >     * <p>If the lock is not available, the current thread becomes
286 >     * disabled for thread scheduling purposes and lies dormant until
287 >     * one of three things happens:
288       *
289 <     * <p>If the current thread already holds the lock then the hold
290 <     * count is incremented by one and the method returns immediately.
289 >     * <ul>
290 >     *
291 >     * <li>The lock becomes available, in which case the current
292 >     * sequence number is returned.
293 >     *
294 >     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
295 >     * the current thread, in which case this method throws
296 >     * {@link InterruptedException}.
297       *
298 <     * <p>If the lock is held by another thread then the
299 <     * current thread becomes disabled for thread scheduling
300 <     * purposes and lies dormant until the lock has been acquired,
301 <     * at which time the lock hold count is set to one.
298 >     * <li>The specified waiting time elapses, in which case
299 >     * this method throws {@link TimeoutException}.
300 >     *
301 >     * </ul>
302 >     *
303 >     * @param timeout the time to wait for availability
304 >     * @param unit the time unit of the timeout argument
305 >     * @return the current sequence number if the lock is available
306 >     *         upon return from this method.
307 >     * @throws InterruptedException if the current thread is interrupted
308 >     * @throws TimeoutException if the lock was not available within
309 >     * the specified waiting time.
310 >     * @throws NullPointerException if the time unit is null
311 >     */
312 >    public long tryAwaitAvailability(long timeout, TimeUnit unit)
313 >        throws InterruptedException, TimeoutException {
314 >        return sync.tryAwaitAvailability(unit.toNanos(timeout));
315 >    }
316 >
317 >    /**
318 >     * Acquires the lock.
319 >     *
320 >     * <p>If the current thread already holds this lock then the hold count
321 >     * is incremented by one and the method returns immediately without
322 >     * incrementing the sequence number.
323 >     *
324 >     * <p>If this lock not held by another thread, this method
325 >     * increments the sequence number (which thus becomes an odd
326 >     * number), sets the lock hold count to one, and returns
327 >     * immediately.
328 >     *
329 >     * <p>If the lock is held by another thread then the current
330 >     * thread may retry acquiring this lock, depending on the {@code
331 >     * spin} count established in constructor.  If the lock is still
332 >     * not acquired, the current thread becomes disabled for thread
333 >     * scheduling purposes and lies dormant until enabled by
334 >     * some other thread releasing the lock.
335       */
336      public void lock() { sync.lock(); }
337  
# Line 279 | Line 339 | public class SequenceLock implements Loc
339       * Acquires the lock unless the current thread is
340       * {@linkplain Thread#interrupt interrupted}.
341       *
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     *
342       * <p>If the current thread already holds this lock then the hold count
343 <     * is incremented by one and the method returns immediately.
343 >     * is incremented by one and the method returns immediately without
344 >     * incrementing the sequence number.
345       *
346 <     * <p>If the lock is held by another thread then the
347 <     * current thread becomes disabled for thread scheduling
348 <     * purposes and lies dormant until one of two things happens:
346 >     * <p>If this lock not held by another thread, this method
347 >     * increments the sequence number (which thus becomes an odd
348 >     * number), sets the lock hold count to one, and returns
349 >     * immediately.
350 >     *
351 >     * <p>If the lock is held by another thread then the current
352 >     * thread may retry acquiring this lock, depending on the {@code
353 >     * spin} count established in constructor.  If the lock is still
354 >     * not acquired, the current thread becomes disabled for thread
355 >     * scheduling purposes and lies dormant until one of two things
356 >     * happens:
357       *
358       * <ul>
359       *
# Line 299 | Line 365 | public class SequenceLock implements Loc
365       * </ul>
366       *
367       * <p>If the lock is acquired by the current thread then the lock hold
368 <     * count is set to one.
368 >     * count is set to one and the sequence number is incremented.
369       *
370       * <p>If the current thread:
371       *
# Line 322 | Line 388 | public class SequenceLock implements Loc
388       * @throws InterruptedException if the current thread is interrupted
389       */
390      public void lockInterruptibly() throws InterruptedException {
391 <        sync.acquireInterruptibly(1);
391 >        sync.acquireInterruptibly(1L);
392      }
393  
394      /**
395       * Acquires the lock only if it is not held by another thread at the time
396       * of invocation.
397       *
398 <     * <p>Acquires the lock if it is not held by another thread and
399 <     * returns immediately with the value {@code true}, setting the
400 <     * lock hold count to one.
398 >     * <p>If the current thread already holds this lock then the hold
399 >     * count is incremented by one and the method returns {@code true}
400 >     * without incrementing the sequence number.
401 >     *
402 >     * <p>If this lock not held by another thread, this method
403 >     * increments the sequence number (which thus becomes an odd
404 >     * number), sets the lock hold count to one, and returns {@code
405 >     * true}.
406       *
407 <     * <p> If the current thread already holds this lock then the hold
408 <     * 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}.
407 >     * <p>If the lock is held by another thread then this method
408 >     * returns {@code false}.
409       *
410       * @return {@code true} if the lock was free and was acquired by the
411       *         current thread, or the lock was already held by the current
412       *         thread; and {@code false} otherwise
413       */
414 <    public boolean tryLock() { return sync.tryAcquire(1); }
414 >    public boolean tryLock() { return sync.tryAcquire(1L); }
415  
416      /**
417       * Acquires the lock if it is not held by another thread within the given
418       * waiting time and the current thread has not been
419       * {@linkplain Thread#interrupt interrupted}.
420       *
421 <     * <p>Acquires the lock if it is not held by another thread and returns
422 <     * immediately with the value {@code true}, setting the lock hold count
423 <     * to one. If this lock has been set to use a fair ordering policy then
424 <     * an available lock <em>will not</em> be acquired if any other threads
425 <     * are waiting for the lock. This is in contrast to the {@link #tryLock()}
426 <     * method. If you want a timed {@code tryLock} that does permit barging on
427 <     * a fair lock then combine the timed and un-timed forms together:
428 <     *
429 <     *  <pre> {@code
430 <     * if (lock.tryLock() ||
431 <     *     lock.tryLock(timeout, unit)) {
432 <     *   ...
433 <     * }}</pre>
434 <     *
435 <     * <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:
421 >     * <p>If the current thread already holds this lock then the hold count
422 >     * is incremented by one and the method returns immediately without
423 >     * incrementing the sequence number.
424 >     *
425 >     * <p>If this lock not held by another thread, this method
426 >     * increments the sequence number (which thus becomes an odd
427 >     * number), sets the lock hold count to one, and returns
428 >     * immediately.
429 >     *
430 >     * <p>If the lock is held by another thread then the current
431 >     * thread may retry acquiring this lock, depending on the {@code
432 >     * spin} count established in constructor.  If the lock is still
433 >     * not acquired, the current thread becomes disabled for thread
434 >     * scheduling purposes and lies dormant until one of three things
435 >     * happens:
436       *
437       * <ul>
438       *
# Line 420 | Line 482 | public class SequenceLock implements Loc
482       */
483      public boolean tryLock(long timeout, TimeUnit unit)
484          throws InterruptedException {
485 <        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
485 >        return sync.tryAcquireNanos(1L, unit.toNanos(timeout));
486      }
487  
488      /**
489       * Attempts to release this lock.
490       *
491 <     * <p>If the current thread is the holder of this lock then the hold
492 <     * count is decremented.  If the hold count is now zero then the lock
493 <     * is released.  If the current thread is not the holder of this
494 <     * lock then {@link IllegalMonitorStateException} is thrown.
491 >     * <p>If the current thread is the holder of this lock then the
492 >     * hold count is decremented.  If the hold count is now zero then
493 >     * the sequence number is incremented (thus becoming an even
494 >     * number) and the lock is released.  If the current thread is not
495 >     * the holder of this lock then {@link
496 >     * IllegalMonitorStateException} is thrown.
497       *
498       * @throws IllegalMonitorStateException if the current thread does not
499       *         hold this lock
# Line 437 | Line 501 | public class SequenceLock implements Loc
501      public void unlock()              { sync.release(1); }
502  
503      /**
504 <     * Returns a {@link Condition} instance for use with this
505 <     * {@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>
504 >     * Throws UnsupportedOperationException. SequenceLocks
505 >     * do not support Condition objects.
506       *
507 <     * @return the Condition object
507 >     * @throws UnsupportedOperationException
508       */
509 <    public Condition newCondition()   { return sync.newCondition(); }
509 >    public Condition newCondition()   {
510 >        throw new UnsupportedOperationException();
511 >    }
512  
513      /**
514       * Queries the number of holds on this lock by the current thread.
# Line 481 | Line 517 | public class SequenceLock implements Loc
517       * matched by an unlock action.
518       *
519       * <p>The hold count information is typically only used for testing and
520 <     * debugging purposes.
520 >     * debugging purposes.
521       *
522       * @return the number of holds on this lock by the current thread,
523       *         or zero if this lock is not held by the current thread
# Line 580 | Line 616 | public class SequenceLock implements Loc
616      }
617  
618      /**
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    /**
619       * Returns a string identifying this lock, as well as its lock state.
620       * The state, in brackets, includes either the String {@code "Unlocked"}
621       * or the String {@code "Locked by"} followed by the
# Line 666 | Line 631 | public class SequenceLock implements Loc
631      }
632  
633   }
634 <            
634 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines