模块  java.base

Class StampedLock

  • 实现的所有接口
    Serializable

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

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

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

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

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

    由于它支持跨多种锁定模式的协调使用,因此该类不直接实现LockReadWriteLock接口。 然而,StampedLock可以看作asReadLock()asWriteLock() ,或asReadWriteLock()中,仅需要在一组相关联的功能的应用程序。

    样品使用。 以下说明了维护简单二维点的类中的一些用法习惯用法。 示例代码说明了一些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 moveIfAtOrigin(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); } } } 
    从以下版本开始:
    1.8
    另请参见:
    Serialized Form
    • 构造方法详细信息

      • 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 - 一张邮票
        结果
        有效的读取标记,或失败时为零
      • tryConvertToOptimisticRead

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

        public boolean tryUnlockWrite()
        如果保持写锁定,则释放写锁定,而不需要标记值。 此方法可用于错误后的恢复。
        结果
        如果锁定, true ,否则为false
      • tryUnlockRead

        public boolean tryUnlockRead()
        如果保持读取锁定,则释放一次,而不需要标记值。 此方法可用于错误后的恢复。
        结果
        如果读锁定被保持, true ,否则为false
      • 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()
        返回标识此锁的字符串及其锁定状态。 括号中的状态包括String "Unlocked"或String "Write-locked"或String "Read-locks:"后跟当前保持的读锁数。
        重写:
        toStringObject
        结果
        标识此锁的字符串及其锁定状态