APIdia Launch Partner
Top Description Inners Fields Constructors Methods
java.util.concurrent.locks

public Class StampedLock

extends Object
implements Serializable
Class Inheritance
All Implemented Interfaces
java.io.Serializable
Imports
java.util.concurrent.TimeUnit, jdk.internal.misc.Unsafe, jdk.internal.vm.annotation.ReservedStackAccess

A capability-based lock with three modes for controlling read/write access. The state of a StampedLock consists of a version and mode. Lock acquisition methods return a stamp that represents and controls access with respect to a lock state; "try" versions of these methods may instead return the special value zero to represent failure to acquire access. Lock release and conversion methods require stamps as arguments, and fail if they do not match the state of the lock. The three modes are:

This class also supports methods that conditionally provide conversions across the three modes. For example, method tryConvertToWriteLock attempts to "upgrade" a mode, returning a valid write stamp if (1) already in writing mode (2) in reading mode and there are no other readers or (3) in optimistic read mode and the lock is available. The forms of these methods are designed to help reduce some of the code bloat that otherwise occurs in retry-based designs.

StampedLocks are designed for use as internal utilities in the development of thread-safe components. Their use relies on knowledge of the internal properties of the data, objects, and methods they are protecting. They are not reentrant, so locked bodies should not call other unknown methods that may try to re-acquire locks (although you may pass a stamp to other methods that can use or convert it). The use of read lock modes relies on the associated code sections being side-effect-free. Unvalidated optimistic read sections cannot call methods that are not known to tolerate potential inconsistencies. Stamps use finite representations, and are not cryptographically secure (i.e., a valid stamp may be guessable). Stamp values may recycle after (no sooner than) one year of continuous operation. A stamp held without use or validation for longer than this period may fail to validate correctly. StampedLocks are serializable, but always deserialize into initial unlocked state, so they are not useful for remote locking.

Like Semaphore, but unlike most Lock implementations, StampedLocks have no notion of ownership. Locks acquired in one thread can be released or converted in another.

The scheduling policy of StampedLock does not consistently prefer readers over writers or vice versa. All "try" methods are best-effort and do not necessarily conform to any scheduling or fairness policy. A zero return from any "try" method for acquiring or converting locks does not carry any information about the state of the lock; a subsequent invocation may succeed.

Because it supports coordinated usage across multiple lock modes, this class does not directly implement the Lock or ReadWriteLock interfaces. However, a StampedLock may be viewed asReadLock(), asWriteLock(), or asReadWriteLock() in applications requiring only the associated set of functionality.

Memory Synchronization. Methods with the effect of successfully locking in any mode have the same memory synchronization effects as a Lock action, as described in Chapter 17 of The Java Language Specification. Methods successfully unlocking in write mode have the same memory synchronization effects as an Unlock action. In optimistic read usages, actions prior to the most recent write mode unlock action are guaranteed to happen-before those following a tryOptimisticRead only if a later validate returns true; otherwise there is no guarantee that the reads between tryOptimisticRead and validate obtain a consistent snapshot.

Sample Usage. The following illustrates some usage idioms in a class that maintains simple two-dimensional points. The sample code illustrates some try/catch conventions even though they are not strictly needed here because no exceptions can occur in their bodies.

 class Point {
  private double x, y;
  private final StampedLock sl = new StampedLock();

  // an exclusively locked method
  void move(double deltaX, double deltaY) {
    long stamp = sl.writeLock();
    try {
      x += deltaX;
      y += deltaY;
    } finally {
      sl.unlockWrite(stamp);
    }
  }

  // a read-only method
  // upgrade from optimistic read to read lock
  double distanceFromOrigin() {
    long stamp = sl.tryOptimisticRead();
    try {
      retryHoldingLock: for (;; stamp = sl.readLock()) {
        if (stamp == 0L)
          continue retryHoldingLock;
        // possibly racy reads
        double currentX = x;
        double currentY = y;
        if (!sl.validate(stamp))
          continue retryHoldingLock;
        return Math.hypot(currentX, currentY);
      }
    } finally {
      if (StampedLock.isReadLockStamp(stamp))
        sl.unlockRead(stamp);
    }
  }

  // upgrade from optimistic read to write lock
  void moveIfAtOrigin(double newX, double newY) {
    long stamp = sl.tryOptimisticRead();
    try {
      retryHoldingLock: for (;; stamp = sl.writeLock()) {
        if (stamp == 0L)
          continue retryHoldingLock;
        // possibly racy reads
        double currentX = x;
        double currentY = y;
        if (!sl.validate(stamp))
          continue retryHoldingLock;
        if (currentX != 0.0 || currentY != 0.0)
          break;
        stamp = sl.tryConvertToWriteLock(stamp);
        if (stamp == 0L)
          continue retryHoldingLock;
        // exclusive access
        x = newX;
        y = newY;
        return;
      }
    } finally {
      if (StampedLock.isWriteLockStamp(stamp))
        sl.unlockWrite(stamp);
    }
  }

  // upgrade read lock to write lock
  void moveIfAtOrigin2(double newX, double newY) {
    long stamp = sl.readLock();
    try {
      while (x == 0.0 && y == 0.0) {
        long ws = sl.tryConvertToWriteLock(stamp);
        if (ws != 0L) {
          stamp = ws;
          x = newX;
          y = newY;
          break;
        }
        else {
          sl.unlockRead(stamp);
          stamp = sl.writeLock();
        }
      }
    } finally {
      sl.unlock(stamp);
    }
  }
}
Author
Doug Lea
Since
1.8
Java Language Specification
17.4 Memory Model

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv abstract static class
pack-priv static class
pack-priv class
pack-priv class
pack-priv class
pack-priv static class

Field Summary

Modifier and TypeField and Description
private static final long
pack-priv static final int
private transient volatile StampedLock.Node
head

Head of CLH queue

private static final long
private static final long
private static final int
LG_READERS

The number of bits to use for reader count before overflowing

private static final long
ORIGIN

Initial value for lock state; avoids failure value zero.

private static final long
private transient int
readerOverflow

extra reader count when state read count saturated

pack-priv transient StampedLock.ReadLockView
pack-priv transient StampedLock.ReadWriteLockView
private static final long
private static final long
private static final long
private static final long
private static final long
private transient volatile long
state

Lock sequence/state

private static final long
private transient volatile StampedLock.Node
tail

Tail (last) of CLH queue

private static final long
private static final Unsafe
U

pack-priv static final int
private static final long
pack-priv transient StampedLock.WriteLockView

Constructor Summary

AccessConstructor and Description
public
StampedLock()

Creates a new lock, initially in unlocked state.

Method Summary

Modifier and TypeMethod and Description
private long

Returns:

next state, or INTERRUPTED
acquireRead
(boolean
true if should check interrupts and if so return INTERRUPTED
interruptible
,
boolean
if true use timed waits
timed
,
long
the System.nanoTime value to timeout at (and return zero)
time
)

See above for explanation.

private long

Returns:

next state, or INTERRUPTED
acquireWrite
(boolean
true if should check interrupts and if so return INTERRUPTED
interruptible
,
boolean
if true use timed waits
timed
,
long
the System.nanoTime value to timeout at (and return zero)
time
)

For explanation, see above and AbstractQueuedSynchronizer internal documentation.

public Lock

Returns:

the lock
asReadLock
()

Returns a plain Lock view of this StampedLock in which the Lock#lock method is mapped to readLock, and similarly for other methods.

public ReadWriteLock

Returns:

the lock
asReadWriteLock
()

Returns a ReadWriteLock view of this StampedLock in which the ReadWriteLock#readLock() method is mapped to asReadLock(), and ReadWriteLock#writeLock() to asWriteLock().

public Lock

Returns:

the lock
asWriteLock
()

Returns a plain Lock view of this StampedLock in which the Lock#lock method is mapped to writeLock, and similarly for other methods.

private void
cancelAcquire(StampedLock.Node
the waiter (may be null if not yet enqueued)
node
)

If node non-null, forces cancel status and unsplices it from queue, wakes up any cowaiters, and possibly wakes up successor to recheck status.

private void
cancelCowaiter(StampedLock.ReaderNode
if non-null, the waiter
node
,
StampedLock.ReaderNode
if non-null, the node heading cowaiters list
leader
)

If node non-null, forces cancel status and unsplices from leader's cowaiters list unless/until it is also cancelled.

private boolean
casState(long expect, long update)

private boolean
private void
cleanQueue()

Possibly repeatedly traverses from tail, unsplicing cancelled nodes until none are found.

private int
getReadLockCount(long s)

Returns combined state-held and overflow read count for given state s.

public int

Returns:

the number of read locks held
getReadLockCount
()

Queries the number of read locks held for this lock.

public static boolean

Returns:

true if the stamp was returned by a successful read-lock or write-lock operation
isLockStamp
(long
a stamp returned by a previous StampedLock operation
stamp
)

Tells whether a stamp represents holding a lock.

public static boolean

Returns:

true if the stamp was returned by a successful optimistic read operation, that is, a non-zero return from tryOptimisticRead() or tryConvertToOptimisticRead(long)
isOptimisticReadStamp
(long
a stamp returned by a previous StampedLock operation
stamp
)

Tells whether a stamp represents a successful optimistic read.

public boolean

Returns:

true if the lock is currently held non-exclusively
isReadLocked
()

Returns true if the lock is currently held non-exclusively.

public static boolean

Returns:

true if the stamp was returned by a successful read-lock operation
isReadLockStamp
(long
a stamp returned by a previous StampedLock operation
stamp
)

Tells whether a stamp represents holding a lock non-exclusively.

public boolean

Returns:

true if the lock is currently held exclusively
isWriteLocked
()

Returns true if the lock is currently held exclusively.

public static boolean

Returns:

true if the stamp was returned by a successful write-lock operation
isWriteLockStamp
(long
a stamp returned by a previous StampedLock operation
stamp
)

Tells whether a stamp represents holding a lock exclusively.

public long

Returns:

a read stamp that can be used to unlock or convert mode
readLock
()

Non-exclusively acquires the lock, blocking if necessary until available.

public long

Returns:

a read stamp that can be used to unlock or convert mode
readLockInterruptibly
()

Non-exclusively acquires the lock, blocking if necessary until available or the current thread is interrupted.

private void
private long
releaseWrite(long s)

private static void
signalCowaiters(StampedLock.ReaderNode node)

Removes and unparks all cowaiters of node, if it exists.

pack-priv static final void
signalNext(StampedLock.Node h)

Wakes up the successor of given node, if one exists, and unsets its WAITING status to avoid park race.

private long
spinLockOnOOME(boolean write, boolean interruptible, boolean timed, long time)

Fallback upon encountering OutOfMemoryErrors

public String

Returns:

a string identifying this lock, as well as its lock state
toString
()

Overrides java.lang.Object.toString.

Returns a string identifying this lock, as well as its lock state.

private long
private long
public long

Returns:

a valid optimistic read stamp, or zero on failure
tryConvertToOptimisticRead
(long
a stamp
stamp
)

If the lock state matches the given stamp then, atomically, if the stamp represents holding a lock, releases it and returns an observation stamp.

public long

Returns:

a valid read stamp, or zero on failure
tryConvertToReadLock
(long
a stamp
stamp
)

If the lock state matches the given stamp, atomically performs one of the following actions.

public long

Returns:

a valid write stamp, or zero on failure
tryConvertToWriteLock
(long
a stamp
stamp
)

If the lock state matches the given stamp, atomically performs one of the following actions.

private long

Returns:

new stamp on success, else zero
tryDecReaderOverflow
(long
a reader overflow stamp: (s & ABITS) >= RFULL
s
)

Tries to decrement readerOverflow.

private long

Returns:

new stamp on success, else zero
tryIncReaderOverflow
(long
a reader overflow stamp: (s & ABITS) >= RFULL
s
)

Tries to increment readerOverflow by first setting state access bits value to RBITS, indicating hold of spinlock, then updating, then releasing.

private void
tryInitializeHead(StampedLock.Node h)

tries once to CAS a new dummy node for head

public long

Returns:

a valid optimistic read stamp, or zero if exclusively locked
tryOptimisticRead
()

Returns a stamp that can later be validated, or zero if exclusively locked.

public long

Returns:

a read stamp that can be used to unlock or convert mode, or zero if the lock is not available
tryReadLock
()

Non-exclusively acquires the lock if it is immediately available.

public long

Returns:

a read stamp that can be used to unlock or convert mode, or zero if the lock is not available
tryReadLock
(long
the maximum time to wait for the lock
time
,
TimeUnit
the time unit of the time argument
unit
)

Non-exclusively acquires the lock if it is available within the given time and the current thread has not been interrupted.

public boolean

Returns:

true if the read lock was held, else false
tryUnlockRead
()

Releases one hold of the read lock if it is held, without requiring a stamp value.

public boolean

Returns:

true if the lock was held, else false
tryUnlockWrite
()

Releases the write lock if it is held, without requiring a stamp value.

public long

Returns:

a write stamp that can be used to unlock or convert mode, or zero if the lock is not available
tryWriteLock
()

Exclusively acquires the lock if it is immediately available.

public long

Returns:

a write stamp that can be used to unlock or convert mode, or zero if the lock is not available
tryWriteLock
(long
the maximum time to wait for the lock
time
,
TimeUnit
the time unit of the time argument
unit
)

Exclusively acquires the lock if it is available within the given time and the current thread has not been interrupted.

private void
unlinkCowaiter(StampedLock.ReaderNode node, StampedLock.ReaderNode leader)

If leader exists, possibly repeatedly traverses cowaiters, unsplicing the given cancelled node until not found.

public void
unlock(long
a stamp returned by a lock operation
stamp
)

If the lock state matches the given stamp, releases the corresponding mode of the lock.

public void
unlockRead(long
a stamp returned by a read-lock operation
stamp
)

If the lock state matches the given stamp, releases the non-exclusive lock.

public void
unlockWrite(long
a stamp returned by a write-lock operation
stamp
)

If the lock state matches the given stamp, releases the exclusive lock.

private static long
unlockWriteState(long
a write-locked state (or stamp)
s
)

Returns an unlocked state, incrementing the version and avoiding special failure value 0L.

pack-priv final void
pack-priv final void
public boolean

Returns:

true if the lock has not been exclusively acquired since issuance of the given stamp; else false
validate
(long
a stamp
stamp
)

Returns true if the lock has not been exclusively acquired since issuance of the given stamp.

public long

Returns:

a write stamp that can be used to unlock or convert mode
writeLock
()

Exclusively acquires the lock, blocking if necessary until available.

public long

Returns:

a write stamp that can be used to unlock or convert mode
writeLockInterruptibly
()

Exclusively acquires the lock, blocking if necessary until available or the current thread is interrupted.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAllwaitwaitwait