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.7 by dl, Sun Jul 17 15:07:11 2011 UTC vs.
Revision 1.14 by jsr166, Sat Sep 10 01:44:53 2011 UTC

# Line 23 | Line 23 | import java.io.IOException;
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 will retry at least the
31 < * given 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   * 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}.
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.
# Line 42 | Line 43 | import java.io.IOException;
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 availability, 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
56 > *  <pre> {@code
57   * class Point {
58 < *     private float x, y;
59 < *     private final SequenceLock sl = new SequenceLock();
58 > *   private volatile double x, y;
59 > *   private final SequenceLock sl = new SequenceLock();
60   *
61 < *     void move(float deltaX, float deltaY) { // an exclusively locked method
62 < *        sl.lock();
63 < *        try {
64 < *            x += deltaX;
65 < *            y += deltaY;
66 < *        } finally {
67 < *          sl.unlock();
68 < *      }
69 < *  }
61 > *   // an exclusively locked method
62 > *   void move(double deltaX, double deltaY) {
63 > *     sl.lock();
64 > *     try {
65 > *       x += deltaX;
66 > *       y += deltaY;
67 > *     } finally {
68 > *       sl.unlock();
69 > *     }
70 > *   }
71   *
72 < *  float distanceFromOriginV1() { // A read-only method
73 < *      float currentX, currentY;
74 < *      long seq;
75 < *      do {
76 < *          seq = sl.awaitAvailability();
77 < *          currentX = x;
78 < *          currentY = y;
79 < *      } while (sl.getSequence() != seq); // retry if sequence changed
80 < *      return (float)Math.sqrt(currentX * currentX + currentY * currentY);
81 < *  }
72 > *   // A read-only method
73 > *   double distanceFromOriginV1() {
74 > *     double currentX, currentY;
75 > *     long seq;
76 > *     do {
77 > *       seq = sl.awaitAvailability();
78 > *       currentX = x;
79 > *       currentY = y;
80 > *     } while (sl.getSequence() != seq); // retry if sequence changed
81 > *     return Math.sqrt(currentX * currentX + currentY * currentY);
82 > *   }
83   *
84 < *  float distanceFromOriginV2() { // Uses bounded retries before locking
85 < *      float currentX, currentY;
86 < *      long seq;
87 < *      int retries = RETRIES_BEFORE_LOCKING; // for example 8
88 < *      try {
89 < *        do {
90 < *           if (--retries < 0)
91 < *              sl.lock();
92 < *           seq = sl.awaitAvailability();
93 < *           currentX = x;
94 < *           currentY = y;
95 < *        } while (sl.getSequence() != seq);
96 < *      } finally {
97 < *        if (retries < 0)
98 < *           sl.unlock();
99 < *      }
100 < *      return (float)Math.sqrt(currentX * currentX + currentY * currentY);
101 < *  }
102 < *}}</pre>
84 > *   // Uses bounded retries before locking
85 > *   double distanceFromOriginV2() {
86 > *     double currentX, currentY;
87 > *     long seq;
88 > *     int retries = RETRIES_BEFORE_LOCKING; // for example 8
89 > *     try {
90 > *       do {
91 > *         if (--retries < 0)
92 > *           sl.lock();
93 > *         seq = sl.awaitAvailability();
94 > *         currentX = x;
95 > *         currentY = y;
96 > *       } while (sl.getSequence() != seq);
97 > *     } finally {
98 > *       if (retries < 0)
99 > *         sl.unlock();
100 > *     }
101 > *     return Math.sqrt(currentX * currentX + currentY * currentY);
102 > *   }
103 > * }}</pre>
104   *
105   * @since 1.8
106   * @author Doug Lea
# Line 111 | Line 117 | public class SequenceLock implements Loc
117          /**
118           * The number of reentrant holds on this lock. Uses a long for
119           * compatibility with other AbstractQueuedLongSynchronizer
120 <         * operations.
120 >         * operations. Accessed only by lock holder.
121           */
122          long holds;
123  
# Line 185 | Line 191 | public class SequenceLock implements Loc
191  
192          final long awaitAvailability() {
193              long s;
188            int k = spins;
194              while (((s = getState()) & 1L) != 0L &&
195                     getExclusiveOwnerThread() != Thread.currentThread()) {
196 <                if (k > 0)
197 <                    --k;
193 <                else {
194 <                    acquireShared(1L);
195 <                    releaseShared(1L);
196 <                }
196 >                acquireShared(1L);
197 >                releaseShared(1L);
198              }
199              return s;
200          }
# Line 248 | Line 249 | public class SequenceLock implements Loc
249  
250      /**
251       * Creates an instance of {@code SequenceLock} with the default
252 <     * number of retry attempts to lock or await release before
252 <     * blocking.
252 >     * number of retry attempts to acquire the lock before blocking.
253       */
254      public SequenceLock() { sync = new Sync(DEFAULT_SPINS); }
255  
256      /**
257 <     * Creates an instance of {@code SequenceLock} that
258 <     * will retry attempts to lock or await release
259 <     * at least the given number times before blocking.
257 >     * Creates an instance of {@code SequenceLock} that will retry
258 >     * attempts to acquire the lock at least the given number times
259 >     * before blocking.
260       */
261      public SequenceLock(int spins) { sync = new Sync(spins); }
262  
# Line 306 | Line 306 | public class SequenceLock implements Loc
306       * @param timeout the time to wait for availability
307       * @param unit the time unit of the timeout argument
308       * @return the current sequence number if the lock is available
309 <     *         upon return from this method.
309 >     *         upon return from this method
310       * @throws InterruptedException if the current thread is interrupted
311       * @throws TimeoutException if the lock was not available within
312 <     * the specified waiting time.
312 >     * the specified waiting time
313       * @throws NullPointerException if the time unit is null
314       */
315      public long tryAwaitAvailability(long timeout, TimeUnit unit)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines