< prev index next >

src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java

Print this page
8211283: Miscellaneous changes imported from jsr166 CVS 2018-11
Reviewed-by: martin, chegar


  48  * these methods may instead return the special value zero to
  49  * represent failure to acquire access. Lock release and conversion
  50  * methods require stamps as arguments, and fail if they do not match
  51  * the state of the lock. The three modes are:
  52  *
  53  * <ul>
  54  *
  55  *  <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
  56  *   waiting for exclusive access, returning a stamp that can be used
  57  *   in method {@link #unlockWrite} to release the lock. Untimed and
  58  *   timed versions of {@code tryWriteLock} are also provided. When
  59  *   the lock is held in write mode, no read locks may be obtained,
  60  *   and all optimistic read validations will fail.
  61  *
  62  *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
  63  *   waiting for non-exclusive access, returning a stamp that can be
  64  *   used in method {@link #unlockRead} to release the lock. Untimed
  65  *   and timed versions of {@code tryReadLock} are also provided.
  66  *
  67  *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
  68  *   returns a non-zero stamp only if the lock is not currently held
  69  *   in write mode. Method {@link #validate} returns true if the lock
  70  *   has not been acquired in write mode since obtaining a given
  71  *   stamp.  This mode can be thought of as an extremely weak version
  72  *   of a read-lock, that can be broken by a writer at any time.  The
  73  *   use of optimistic mode for short read-only code segments often
  74  *   reduces contention and improves throughput.  However, its use is
  75  *   inherently fragile.  Optimistic read sections should only read
  76  *   fields and hold them in local variables for later use after
  77  *   validation. Fields read while in optimistic mode may be wildly
  78  *   inconsistent, so usage applies only when you are familiar enough
  79  *   with data representations to check consistency and/or repeatedly
  80  *   invoke method {@code validate()}.  For example, such steps are
  81  *   typically required when first reading an object or array
  82  *   reference, and then accessing one of its fields, elements or
  83  *   methods.

  84  *
  85  * </ul>
  86  *
  87  * <p>This class also supports methods that conditionally provide
  88  * conversions across the three modes. For example, method {@link
  89  * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
  90  * a valid write stamp if (1) already in writing mode (2) in reading
  91  * mode and there are no other readers or (3) in optimistic mode and
  92  * the lock is available. The forms of these methods are designed to
  93  * help reduce some of the code bloat that otherwise occurs in
  94  * retry-based designs.
  95  *
  96  * <p>StampedLocks are designed for use as internal utilities in the
  97  * development of thread-safe components. Their use relies on
  98  * knowledge of the internal properties of the data, objects, and
  99  * methods they are protecting.  They are not reentrant, so locked
 100  * bodies should not call other unknown methods that may try to
 101  * re-acquire locks (although you may pass a stamp to other methods
 102  * that can use or convert it).  The use of read lock modes relies on
 103  * the associated code sections being side-effect-free.  Unvalidated
 104  * optimistic read sections cannot call methods that are not known to
 105  * tolerate potential inconsistencies.  Stamps use finite
 106  * representations, and are not cryptographically secure (i.e., a
 107  * valid stamp may be guessable). Stamp values may recycle after (no
 108  * sooner than) one year of continuous operation. A stamp held without
 109  * use or validation for longer than this period may fail to validate
 110  * correctly.  StampedLocks are serializable, but always deserialize
 111  * into initial unlocked state, so they are not useful for remote
 112  * locking.
 113  *
 114  * <p>Like {@link java.util.concurrent.Semaphore Semaphore}, but unlike most
 115  * {@link Lock} implementations, StampedLocks have no notion of ownership.
 116  * Locks acquired in one thread can be released or converted in another.
 117  *
 118  * <p>The scheduling policy of StampedLock does not consistently
 119  * prefer readers over writers or vice versa.  All "try" methods are
 120  * best-effort and do not necessarily conform to any scheduling or
 121  * fairness policy. A zero return from any "try" method for acquiring
 122  * or converting locks does not carry any information about the state
 123  * of the lock; a subsequent invocation may succeed.
 124  *
 125  * <p>Because it supports coordinated usage across multiple lock
 126  * modes, this class does not directly implement the {@link Lock} or
 127  * {@link ReadWriteLock} interfaces. However, a StampedLock may be
 128  * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link
 129  * #asReadWriteLock()} in applications requiring only the associated
 130  * set of functionality.













 131  *
 132  * <p><b>Sample Usage.</b> The following illustrates some usage idioms
 133  * in a class that maintains simple two-dimensional points. The sample
 134  * code illustrates some try/catch conventions even though they are
 135  * not strictly needed here because no exceptions can occur in their
 136  * bodies.
 137  *
 138  * <pre> {@code
 139  * class Point {
 140  *   private double x, y;
 141  *   private final StampedLock sl = new StampedLock();
 142  *
 143  *   // an exclusively locked method
 144  *   void move(double deltaX, double deltaY) {
 145  *     long stamp = sl.writeLock();
 146  *     try {
 147  *       x += deltaX;
 148  *       y += deltaY;
 149  *     } finally {
 150  *       sl.unlockWrite(stamp);




  48  * these methods may instead return the special value zero to
  49  * represent failure to acquire access. Lock release and conversion
  50  * methods require stamps as arguments, and fail if they do not match
  51  * the state of the lock. The three modes are:
  52  *
  53  * <ul>
  54  *
  55  *  <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
  56  *   waiting for exclusive access, returning a stamp that can be used
  57  *   in method {@link #unlockWrite} to release the lock. Untimed and
  58  *   timed versions of {@code tryWriteLock} are also provided. When
  59  *   the lock is held in write mode, no read locks may be obtained,
  60  *   and all optimistic read validations will fail.
  61  *
  62  *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
  63  *   waiting for non-exclusive access, returning a stamp that can be
  64  *   used in method {@link #unlockRead} to release the lock. Untimed
  65  *   and timed versions of {@code tryReadLock} are also provided.
  66  *
  67  *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
  68  *   returns a non-zero stamp only if the lock is not currently held in
  69  *   write mode.  Method {@link #validate} returns true if the lock has not
  70  *   been acquired in write mode since obtaining a given stamp, in which
  71  *   case all actions prior to the most recent write lock release
  72  *   happen-before actions following the call to {@code tryOptimisticRead}.
  73  *   This mode can be thought of as an extremely weak version of a
  74  *   read-lock, that can be broken by a writer at any time.  The use of
  75  *   optimistic read mode for short read-only code segments often reduces
  76  *   contention and improves throughput.  However, its use is inherently
  77  *   fragile.  Optimistic read sections should only read fields and hold
  78  *   them in local variables for later use after validation. Fields read
  79  *   while in optimistic read mode may be wildly inconsistent, so usage
  80  *   applies only when you are familiar enough with data representations to
  81  *   check consistency and/or repeatedly invoke method {@code validate()}.
  82  *   For example, such steps are typically required when first reading an
  83  *   object or array reference, and then accessing one of its fields,
  84  *   elements or methods.
  85  *
  86  * </ul>
  87  *
  88  * <p>This class also supports methods that conditionally provide
  89  * conversions across the three modes. For example, method {@link
  90  * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
  91  * a valid write stamp if (1) already in writing mode (2) in reading
  92  * mode and there are no other readers or (3) in optimistic read mode
  93  * and the lock is available. The forms of these methods are designed to
  94  * help reduce some of the code bloat that otherwise occurs in
  95  * retry-based designs.
  96  *
  97  * <p>StampedLocks are designed for use as internal utilities in the
  98  * development of thread-safe components. Their use relies on
  99  * knowledge of the internal properties of the data, objects, and
 100  * methods they are protecting.  They are not reentrant, so locked
 101  * bodies should not call other unknown methods that may try to
 102  * re-acquire locks (although you may pass a stamp to other methods
 103  * that can use or convert it).  The use of read lock modes relies on
 104  * the associated code sections being side-effect-free.  Unvalidated
 105  * optimistic read sections cannot call methods that are not known to
 106  * tolerate potential inconsistencies.  Stamps use finite
 107  * representations, and are not cryptographically secure (i.e., a
 108  * valid stamp may be guessable). Stamp values may recycle after (no
 109  * sooner than) one year of continuous operation. A stamp held without
 110  * use or validation for longer than this period may fail to validate
 111  * correctly.  StampedLocks are serializable, but always deserialize
 112  * into initial unlocked state, so they are not useful for remote
 113  * locking.
 114  *
 115  * <p>Like {@link java.util.concurrent.Semaphore Semaphore}, but unlike most
 116  * {@link Lock} implementations, StampedLocks have no notion of ownership.
 117  * Locks acquired in one thread can be released or converted in another.
 118  *
 119  * <p>The scheduling policy of StampedLock does not consistently
 120  * prefer readers over writers or vice versa.  All "try" methods are
 121  * best-effort and do not necessarily conform to any scheduling or
 122  * fairness policy. A zero return from any "try" method for acquiring
 123  * or converting locks does not carry any information about the state
 124  * of the lock; a subsequent invocation may succeed.
 125  *
 126  * <p>Because it supports coordinated usage across multiple lock
 127  * modes, this class does not directly implement the {@link Lock} or
 128  * {@link ReadWriteLock} interfaces. However, a StampedLock may be
 129  * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link
 130  * #asReadWriteLock()} in applications requiring only the associated
 131  * set of functionality.
 132  *
 133  * <p><b>Memory Synchronization.</b> Methods with the effect of
 134  * successfully locking in any mode have the same memory
 135  * synchronization effects as a <em>Lock</em> action described in
 136  * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
 137  * Chapter 17 of <cite>The Java&trade; Language Specification</cite></a>.
 138  * Methods successfully unlocking in write mode have the same memory
 139  * synchronization effects as an <em>Unlock</em> action.  In optimistic
 140  * read usages, actions prior to the most recent write mode unlock action
 141  * are guaranteed to happen-before those following a tryOptimisticRead
 142  * only if a later validate returns true; otherwise there is no guarantee
 143  * that the reads between tryOptimisticRead and validate obtain a
 144  * consistent snapshot.
 145  *
 146  * <p><b>Sample Usage.</b> The following illustrates some usage idioms
 147  * in a class that maintains simple two-dimensional points. The sample
 148  * code illustrates some try/catch conventions even though they are
 149  * not strictly needed here because no exceptions can occur in their
 150  * bodies.
 151  *
 152  * <pre> {@code
 153  * class Point {
 154  *   private double x, y;
 155  *   private final StampedLock sl = new StampedLock();
 156  *
 157  *   // an exclusively locked method
 158  *   void move(double deltaX, double deltaY) {
 159  *     long stamp = sl.writeLock();
 160  *     try {
 161  *       x += deltaX;
 162  *       y += deltaY;
 163  *     } finally {
 164  *       sl.unlockWrite(stamp);


< prev index next >