模块 java.base

类 StampedLock

java.lang.Object
java.util.concurrent.locks.StampedLock
所有已实现的接口:
Serializable

public class StampedLock extends Object implements Serializable
基于能力的锁,具有三种控制读/写访问的模式。 StampedLock 的状态由版本和模式组成。锁获取方法返回一个标记,代表和控制对锁状态的访问;这些方法的“尝试”版本可能会返回特殊值零以表示未能获得访问权。锁释放和转换方法需要时间戳作为参数,如果它们与锁的状态不匹配则失败。这三种模式是:
  • 写作。方法 writeLock() 可能会阻塞等待独占访问,返回一个可以在方法 unlockWrite(long) 中使用的标记来释放锁。还提供了 tryWriteLock 的非定时和定时版本。当锁处于写入模式时,可能无法获得读取锁,并且所有乐观读取验证都将失败。
  • 阅读。方法 readLock() 可能会阻塞等待非独占访问,返回一个可以在方法 unlockRead(long) 中使用的标记来释放锁。还提供了 tryReadLock 的非定时和定时版本。
  • 乐观的阅读。方法 tryOptimisticRead() 仅当锁定当前未处于写入模式时才返回非零标记。如果在获得给定标记后未在写模式下获取锁,则方法 validate(long) 返回 true,在这种情况下,在调用 tryOptimisticRead 之后,最近一次写锁释放之前的所有操作都发生在操作之前。这种模式可以被认为是一个非常弱的读锁版本,可以随时被写入者破坏。对短的只读代码段使用乐观读取模式通常可以减少争用并提高吞吐量。然而,它的使用本质上是脆弱的。乐观读取部分应该只读取字段并将它们保存在局部变量中以供以后在验证后使用。在乐观读取模式下读取的字段可能非常不一致,因此仅当您足够熟悉数据表示以检查一致性和/或重复调用方法 validate() 时才适用。例如,当首先读取对象或数组引用,然后访问其字段、元素或方法之一时,通常需要执行此类步骤。

此类还支持有条件地提供跨三种模式的转换的方法。例如,方法 tryConvertToWriteLock(long) 尝试“升级”模式,如果(1)已经处于写入模式(2)处于读取模式并且没有其他读者或(3)处于乐观读取模式并且锁定是,则返回有效的写入标记可用的。这些方法的形式旨在帮助减少在基于重试的设计中否则会出现的一些代码膨胀。

StampedLocks 设计用作线程安全组件开发中的内部实用程序。它们的使用依赖于对它们所保护的数据、对象和方法的内部属性的了解。它们是不可重入的,因此锁定的主体不应调用其他可能尝试重新获取锁的未知方法(尽管您可以将戳记传递给可以使用或转换它的其他方法)。读取锁定模式的使用依赖于没有副作用的相关代码段。未经验证的乐观读取部分无法调用已知无法容忍潜在不一致的方法。邮票使用有限的表示,并且不是加密安全的(即,一个有效的邮票可能是可猜测的)。邮票值可以在(不早于)连续运行一年后回收。超过此期限而未使用或验证的邮票可能无法正确验证。 StampedLocks 是可序列化的,但总是反序列化为初始解锁状态,因此它们对远程锁定没有用。

Semaphore 一样,但与大多数 Lock 实现不同,StampedLocks 没有所有权的概念。在一个线程中获取的锁可以在另一个线程中释放或转换。

StampedLock 的调度策略并不总是优先于读者而不是作者,反之亦然。所有“尝试”方法都是尽力而为,不一定符合任何调度或公平策略。任何获取或转换锁的“try”方法的零返回不携带任何关于锁状态的信息;后续调用可能会成功。

因为它支持跨多种锁模式的协调使用,所以这个类不直接实现Lock ReadWriteLock 接口。但是,在仅需要相关功能集的应用程序中,可以查看 StampedLock asReadLock() asWriteLock() asReadWriteLock()

内存同步。在任何模式下成功锁定效果的方法与 Lock 操作具有相同的内存同步效果,如第 17 章所述Java 语言规范.在写入模式下成功解锁的方法与 Unlock 操作具有相同的内存同步效果。在乐观读取用法中,只有在稍后的验证返回 true 时,保证在最近的写入模式解锁操作之前发生的操作先于 tryOptimisticRead 之后的操作;否则无法保证 tryOptimisticRead 和 validate 之间的读取获得一致的快照。

示例用法。下面举例说明维护简单二维点的类中的一些用法习语。示例代码说明了一些 try/catch 约定,尽管这里并不严格需要它们,因为它们的主体中不会出现异常。

 
 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);
   }
  }
 } 
Java 语言规范:
17.4 内存模型
自从:
1.8
参见:
  • 构造方法详细信息

    • StampedLock

      public StampedLock()
      创建一个新锁,最初处于解锁状态。
  • 方法详情

    • writeLock

      public long writeLock()
      独占获取锁,必要时阻塞直到可用。
      返回:
      可用于解锁或转换模式的写入标记
    • tryWriteLock

      public long tryWriteLock()
      如果锁立即可用,则以独占方式获取锁。
      返回:
      可用于解锁或转换模式的写入戳记,如果锁不可用则为零
    • tryWriteLock

      public long tryWriteLock(long time, TimeUnit  unit) throws InterruptedException
      如果在给定时间内可用且当前线程未被中断,则独占获取锁。超时和中断下的行为与为方法 Lock.tryLock(long,TimeUnit) 指定的行为相匹配。
      参数:
      time - 等待锁的最长时间
      unit - time 参数的时间单位
      返回:
      可用于解锁或转换模式的写入戳记,如果锁不可用则为零
      抛出:
      InterruptedException - 如果当前线程在获取锁之前被中断
    • writeLockInterruptibly

      public long writeLockInterruptibly() throws InterruptedException
      独占获取锁,必要时阻塞,直到可用或当前线程被中断。中断下的行为与为方法 Lock.lockInterruptibly() 指定的行为相匹配。
      返回:
      可用于解锁或转换模式的写入标记
      抛出:
      InterruptedException - 如果当前线程在获取锁之前被中断
    • readLock

      public long readLock()
      非独占地获取锁,必要时阻塞直到可用。
      返回:
      可用于解锁或转换模式的已读标记
    • tryReadLock

      public long tryReadLock()
      如果锁立即可用,则非独占地获取锁。
      返回:
      可用于解锁或转换模式的读取标记,如果锁不可用则为零
    • tryReadLock

      public long tryReadLock(long time, TimeUnit  unit) throws InterruptedException
      如果在给定时间内可用且当前线程未被中断,则非独占获取锁。超时和中断下的行为与为方法 Lock.tryLock(long,TimeUnit) 指定的行为相匹配。
      参数:
      time - 等待锁的最长时间
      unit - time 参数的时间单位
      返回:
      可用于解锁或转换模式的读取标记,如果锁不可用则为零
      抛出:
      InterruptedException - 如果当前线程在获取锁之前被中断
    • readLockInterruptibly

      public long readLockInterruptibly() throws InterruptedException
      非独占地获取锁,必要时阻塞直到可用或当前线程被中断。中断下的行为与为方法 Lock.lockInterruptibly() 指定的行为相匹配。
      返回:
      可用于解锁或转换模式的已读标记
      抛出:
      InterruptedException - 如果当前线程在获取锁之前被中断
    • tryOptimisticRead

      public long tryOptimisticRead()
      返回一个稍后可以验证的戳记,如果完全锁定则返回零。
      返回:
      有效的乐观读取标记,如果完全锁定则为零
    • validate

      public boolean validate(long stamp)
      如果自给定戳记发行以来尚未独占获取锁,则返回 true。如果标记为零,则始终返回 false。如果标记表示当前持有的锁,则始终返回 true。使用未从 tryOptimisticRead() 获得的值或此锁的锁定方法调用此方法没有定义的效果或结果。
      参数:
      stamp - 邮票
      返回:
      true 如果自给定印章发行以来尚未独占获取锁;否则为假
    • unlockWrite

      public void unlockWrite(long stamp)
      如果锁定状态与给定的标记匹配,则释放独占锁。
      参数:
      stamp - 写锁操作返回的标记
      抛出:
      IllegalMonitorStateException - 如果戳记与此锁的当前状态不匹配
    • unlockRead

      public void unlockRead(long stamp)
      如果锁定状态与给定的标记匹配,则释放非排他锁。
      参数:
      stamp - 读锁操作返回的标记
      抛出:
      IllegalMonitorStateException - 如果戳记与此锁的当前状态不匹配
    • unlock

      public void unlock(long stamp)
      如果锁定状态与给定的标记匹配,则释放锁定的相应模式。
      参数:
      stamp - 锁定操作返回的标记
      抛出:
      IllegalMonitorStateException - 如果戳记与此锁的当前状态不匹配
    • tryConvertToWriteLock

      public long tryConvertToWriteLock(long stamp)
      如果锁定状态与给定的标记匹配,则自动执行以下操作之一。如果戳记表示持有写锁,则返回它。或者,如果是读锁,如果写锁可用,则释放读锁并返回一个写戳。或者,如果是乐观读取,则仅在立即可用时才返回写入标记。在所有其他情况下,此方法返回零。
      参数:
      stamp - 邮票
      返回:
      有效的写戳记,或失败时为零
    • tryConvertToReadLock

      public long tryConvertToReadLock(long stamp)
      如果锁定状态与给定的标记匹配,则自动执行以下操作之一。如果stamp表示持有写锁,则释放并获得读锁。或者,如果是读锁,则返回它。或者,如果是乐观读取,则获取读取锁并仅在立即可用时才返回读取标记。在所有其他情况下,此方法返回零。
      参数:
      stamp - 邮票
      返回:
      有效的读取标记,或失败时为零
    • tryConvertToOptimisticRead

      public long tryConvertToOptimisticRead(long stamp)
      如果锁定状态与给定的戳记匹配,则原子地,如果该戳记表示持有锁,则释放它并返回一个观察戳记。或者,如果是乐观读取,则在验证后返回它。此方法在所有其他情况下返回零,因此作为“tryUnlock”的一种形式可能很有用。
      参数:
      stamp - 邮票
      返回:
      有效的乐观阅读标记,或失败时为零
    • tryUnlockWrite

      public boolean tryUnlockWrite()
      释放写锁(如果持有),而不需要标记值。此方法可能对错误后的恢复很有用。
      返回:
      true 如果持有锁,否则为 false
    • tryUnlockRead

      public boolean tryUnlockRead()
      释放一个读锁(如果持有),而不需要标记值。此方法可能对错误后的恢复很有用。
      返回:
      true 如果持有读锁,否则为假
    • isWriteLocked

      public boolean isWriteLocked()
      如果锁当前以独占方式持有,则返回 true
      返回:
      true 如果锁当前是独占持有的
    • isReadLocked

      public boolean isReadLocked()
      如果锁当前是非独占持有的,则返回 true
      返回:
      true 如果锁当前是非独占持有的
    • isWriteLockStamp

      public static boolean isWriteLockStamp(long stamp)
      告诉邮票是否代表独占锁。此方法可能与 tryConvertToWriteLock(long) 结合使用,例如:
       
       long stamp = sl.tryOptimisticRead();
       try {
        ...
        stamp = sl.tryConvertToWriteLock(stamp);
        ...
       } finally {
        if (StampedLock.isWriteLockStamp(stamp))
         sl.unlockWrite(stamp);
       } 
      参数:
      stamp - 由先前的 StampedLock 操作返回的戳记
      返回:
      true 如果标记是由成功的写锁定操作返回的
      自从:
      10
    • isReadLockStamp

      public static boolean isReadLockStamp(long stamp)
      告诉邮票是否代表非独占地持有锁。此方法可能与 tryConvertToReadLock(long) 结合使用,例如:
       
       long stamp = sl.tryOptimisticRead();
       try {
        ...
        stamp = sl.tryConvertToReadLock(stamp);
        ...
       } finally {
        if (StampedLock.isReadLockStamp(stamp))
         sl.unlockRead(stamp);
       } 
      参数:
      stamp - 由先前的 StampedLock 操作返回的戳记
      返回:
      true 如果标记是由成功的读锁定操作返回的
      自从:
      10
    • isLockStamp

      public static boolean isLockStamp(long stamp)
      告诉邮票是否代表持有锁。此方法可能与 tryConvertToReadLock(long) tryConvertToWriteLock(long) 结合使用,例如:
       
       long stamp = sl.tryOptimisticRead();
       try {
        ...
        stamp = sl.tryConvertToReadLock(stamp);
        ...
        stamp = sl.tryConvertToWriteLock(stamp);
        ...
       } finally {
        if (StampedLock.isLockStamp(stamp))
         sl.unlock(stamp);
       } 
      参数:
      stamp - 由先前的 StampedLock 操作返回的戳记
      返回:
      true 如果标记是由成功的读锁或写锁操作返回的
      自从:
      10
    • isOptimisticReadStamp

      public static boolean isOptimisticReadStamp(long stamp)
      告诉邮票是否代表成功的乐观阅读。
      参数:
      stamp - 由先前的 StampedLock 操作返回的戳记
      返回:
      true 如果标记是由成功的乐观读取操作返回的,即来自 tryOptimisticRead() tryConvertToOptimisticRead(long) 的非零返回
      自从:
      10
    • getReadLockCount

      public int getReadLockCount()
      查询为此锁持有的读取锁的数量。此方法设计用于监视系统状态,而不用于同步控制。
      返回:
      持有读锁的数量
    • toString

      public String  toString()
      返回标识此锁及其锁定状态的字符串。括号中的状态包括字符串 "Unlocked" 或字符串 "Write-locked" 或字符串 "Read-locks:" 后跟当前持有的读锁数。
      重写:
      toString 在类 Object
      返回:
      标识此锁及其锁定状态的字符串
    • asReadLock

      public Lock  asReadLock()
      返回此 StampedLock 的普通 Lock 视图,其中 Lock.lock() 方法映射到 readLock() ,其他方法也类似。返回的 Lock 不支持 Condition ;方法 Lock.newCondition() 抛出 UnsupportedOperationException
      返回:
    • asWriteLock

      public Lock  asWriteLock()
      返回此 StampedLock 的普通 Lock 视图,其中 Lock.lock() 方法映射到 writeLock() ,其他方法也类似。返回的 Lock 不支持 Condition ;方法 Lock.newCondition() 抛出 UnsupportedOperationException
      返回:
    • asReadWriteLock

      public ReadWriteLock  asReadWriteLock()
      返回此 StampedLock 的 ReadWriteLock 视图,其中 ReadWriteLock.readLock() 方法映射到 asReadLock() ReadWriteLock.writeLock() 映射到 asWriteLock()
      返回: