模块  java.base

Class AbstractQueuedSynchronizer

  • 实现的所有接口
    Serializable

    public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements Serializable
    提供一个框架,用于实现依赖于先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等)。 此类被设计为大多数类型的同步器的有用基础,这些同步器依赖于单个原子int值来表示状态。 子类必须定义更改此状态的受保护方法,并根据要获取或释放的此对象定义该状态的含义。 鉴于这些,本课程中的其他方法执行所有排队和阻塞机制。 子类可以保持其他状态字段,但只以原子方式更新int使用方法操纵值getState()setState(int)compareAndSetState(int, int)被跟踪相对于同步。

    子类应定义为非公共内部帮助程序类,用于实现其封闭类的同步属性。 AbstractQueuedSynchronizer类未实现任何同步接口。 相反,它定义了诸如acquireInterruptibly(int)之类的方法,可以通过具体的锁和相关的同步器来适当调用它们来实现它们的公共方法。

    此类支持默认独占模式和共享模式之一或两者。 在独占模式下获取时,其他线程尝试获取不能成功。 多个线程获取的共享模式可能(但不一定)成功。 这个类不会“理解”这些差异,除非在机械意义上,当共享模式获取成功时,下一个等待线程(如果存在)还必须确定它是否也可以获取。 在不同模式下等待的线程共享相同的FIFO队列。 通常,实现子类仅支持这些模式中的一种,但两者都可以在例如ReadWriteLock发挥作用 仅支持独占模式或仅支持共享模式的子类无需定义支持未使用模式的方法。

    此类定义了一个嵌套的AbstractQueuedSynchronizer.ConditionObject类,可以通过支持独占模式的子类用作Condition实现,方法isHeldExclusively()报告是否针对当前线程独占保持同步,方法release(int)使用当前getState()值调用完全释放此对象,和acquire(int) ,给定此保存的状态值,最终将此对象恢复到其先前获取的状态。 No AbstractQueuedSynchronizer方法否则会创建此类条件,因此如果无法满足此约束,请不要使用它。 AbstractQueuedSynchronizer.ConditionObject的行为当然取决于其同步器实现的语义。

    此类为内部队列提供检查,检测和监视方法,以及条件对象的类似方法。 这些可以根据需要使用AbstractQueuedSynchronizer导出到类中,以实现同步机制。

    此类的序列化仅存储基础原子整数维护状态,因此反序列化对象具有空线程队列。 需要可串行化的典型子类将定义readObject方法,该方法在反序列化时将其恢复为已知的初始状态。

    用法

    使用这个类用作同步的基础上,重新定义以下方法,如适用,通过检查和/或修改使用所述同步状态getState()setState(int)和/或compareAndSetState(int, int)

    默认情况下,这些方法中的每一种都抛出UnsupportedOperationException 这些方法的实现必须是内部线程安全的,并且通常应该是短的而不是阻塞的。 定义这些方法是使用此类的唯一受支持的方法。 所有其他方法都声明为final因为它们不能独立变化。

    您还可以找到AbstractOwnableSynchronizer的继承方法,用于跟踪拥有独占同步器的线程。 建议您使用它们 - 这使监视和诊断工具能够帮助用户确定哪些线程持有锁。

    即使此类基于内部FIFO队列,它也不会自动执行FIFO获取策略。 独占同步的核心采用以下形式:

      Acquire:
         while (!tryAcquire(arg)) {
            enqueue thread if it is not already queued;
            possibly block current thread;
         }
    
     Release:
         if (tryRelease(arg))
            unblock the first queued thread; 
    (共享模式类似,但可能涉及级联信号。)

    因为在采集检查入队之前调用,所以新获取的线程可能闯入其他被阻塞和排队的。 但是,如果需要,您可以通过内部调用一个或多个检查方法来定义tryAcquire和/或tryAcquireShared以禁用tryAcquireShared ,从而提供公平的 FIFO采集顺序。 特别地,最公平同步器可以定义tryAcquire返回false如果hasQueuedPredecessors() (具体地设计成由公平同步器中使用的方法)返回true 其他变化是可能的。

    对于默认的驳船(也称为贪婪放弃车队避让 )策略,吞吐量和可扩展性通常最高。 虽然这不能保证公平或无饥饿,但允许先前排队的线程在稍后排队的线程之前重新进行,并且每次重新保留都有一个无偏见的机会成功对抗传入的线程。 此外,虽然获取不是通常意义上的“旋转”,但它们可能会在阻塞之前执行tryAcquire多次调用以及其他计算。 当仅短暂地保持独占同步时,这给旋转带来了大部分好处,而没有大部分责任。 如果需要,您可以通过先前调用获取具有“快速路径”检查的方法来增强此功能,可能预先检查hasContended()和/或hasQueuedThreads()仅在同步器可能不会发生争用的情况下执行此操作。

    此类通过将其使用范围专门化为可依赖于int状态,获取和释放参数的同步器以及内部FIFO等待队列,为同步提供了高效且可扩展的同步基础。 如果这还不够,您可以使用atomic类,您自己的自定义Queue类和LockSupport阻止支持从较低级别构建同步器。

    用法示例

    这是一个不可重入的互斥锁类,它使用零值表示解锁状态,一个表示锁定状态。 虽然非重入锁并不严格要求记录当前所有者线程,但此类仍然这样做,以便更容易监视使用情况。 它还支持条件并公开一些检测方法:

       class Mutex implements Lock, java.io.Serializable { // Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Acquires the lock if state is zero public boolean tryAcquire(int acquires) { assert acquires == 1; // Otherwise unused if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } // Releases the lock by setting state to zero protected boolean tryRelease(int releases) { assert releases == 1; // Otherwise unused if (!isHeldExclusively()) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Reports whether in locked state public boolean isLocked() { return getState() != 0; } public boolean isHeldExclusively() { // a data race, but safe due to out-of-thin-air guarantees return getExclusiveOwnerThread() == Thread.currentThread(); } // Provides a Condition public Condition newCondition() { return new ConditionObject(); } // Deserializes properly private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } // The sync object does all the hard work. We just forward to it. private final Sync sync = new Sync(); public void lock() { sync.acquire(1); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isLocked(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } } 

    这是一个类似于CountDownLatch的锁存类,只是它只需要一个signal即可触发。 由于锁存器是非排他性的,因此它使用shared获取和释放方法。

       class BooleanLatch { private static class Sync extends AbstractQueuedSynchronizer { boolean isSignalled() { return getState() != 0; } protected int tryAcquireShared(int ignore) { return isSignalled() ? 1 : -1; } protected boolean tryReleaseShared(int ignore) { setState(1); return true; } } private final Sync sync = new Sync(); public boolean isSignalled() { return sync.isSignalled(); } public void signal() { sync.releaseShared(1); } public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } } 
    从以下版本开始:
    1.5
    另请参见:
    Serialized Form
    • 构造方法详细信息

      • AbstractQueuedSynchronizer

        protected AbstractQueuedSynchronizer()
        创建一个初始同步状态为零的新 AbstractQueuedSynchronizer实例。
    • 方法详细信息

      • getState

        protected final int getState()
        返回同步状态的当前值。 此操作具有volatile读取的内存语义。
        结果
        当前的州价值
      • setState

        protected final void setState​(int newState)
        设置同步状态的值。 此操作具有volatile写入的内存语义。
        参数
        newState - 新的州值
      • compareAndSetState

        protected final boolean compareAndSetState​(int expect,
                                                   int update)
        如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。 此操作具有volatile读写的内存语义。
        参数
        expect - 预期值
        update - 新值
        结果
        true如果成功。 错误返回表示实际值不等于预期值。
      • tryAcquire

        protected boolean tryAcquire​(int arg)
        尝试以独占模式获取。 此方法应查询对象的状态是否允许以独占模式获取它,如果是,则获取它。

        执行获取的线程始终调用此方法。 如果此方法报告失败,则获取方法可以对线程进行排队(如果它尚未排队),直到通过某个其他线程的释放来发出信号。 这可以用于实现方法Lock.tryLock()

        默认实现抛出UnsupportedOperationException

        参数
        arg - 获取参数。 此值始终是传递给acquire方法的值,或者是条件wait的条目时保存的值。 否则,该值无法解释,可以代表您喜欢的任何内容。
        结果
        如果成功,请true 成功后,此对象已被获得。
        异常
        IllegalMonitorStateException - 如果获取将此同步器置于非法状态。 必须以一致的方式抛出此异常才能使同步正常工作。
        UnsupportedOperationException - 如果不支持独占模式
      • tryRelease

        protected boolean tryRelease​(int arg)
        尝试将状态设置为以独占模式反映发布。

        执行发布的线程始终调用此方法。

        默认实现抛出UnsupportedOperationException

        参数
        arg - 发布参数。 此值始终是传递给释放方法的值,或者是在进入条件等待时的当前状态值。 否则,该值无法解释,可以代表您喜欢的任何内容。
        结果
        true如果此对象现在处于完全释放状态,则任何等待的线程都可能尝试获取; 否则为false
        异常
        IllegalMonitorStateException - 如果释放将此同步器置于非法状态。 必须以一致的方式抛出此异常才能使同步正常工作。
        UnsupportedOperationException - 如果不支持独占模式
      • tryAcquireShared

        protected int tryAcquireShared​(int arg)
        尝试以共享模式获取。 此方法应查询对象的状态是否允许在共享模式下获取它,如果是,则获取它。

        执行获取的线程始终调用此方法。 如果此方法报告失败,则获取方法可以对线程进行排队(如果它尚未排队),直到通过某个其他线程的释放来发出信号。

        默认实现抛出UnsupportedOperationException

        参数
        arg - 获取参数。 此值始终是传递给acquire方法的值,或者是条件wait的条目时保存的值。 否则,该值无法解释,可以代表您喜欢的任何内容。
        结果
        失败的负面价值; 如果在共享模式下获取成功但没有后续的共享模式获取可以成功,则为零; 如果在共享模式下获取成功并且后续共享模式获取也可能成功,则为正值,在这种情况下,后续等待线程必须检查可用性。 (支持三个不同的返回值使得此方法可用于仅在有时仅采取行动的上下文中。)成功后,此对象已被获取。
        异常
        IllegalMonitorStateException - 如果获取将此同步器置于非法状态。 必须以一致的方式抛出此异常才能使同步正常工作。
        UnsupportedOperationException - 如果不支持共享模式
      • tryReleaseShared

        protected boolean tryReleaseShared​(int arg)
        尝试将状态设置为反映共享模式下的发布。

        执行发布的线程始终调用此方法。

        默认实现抛出UnsupportedOperationException

        参数
        arg - 发布参数。 此值始终是传递给释放方法的值,或者是在进入条件等待时的当前状态值。 否则,该值无法解释,可以代表您喜欢的任何内容。
        结果
        true如果此共享模式的发布可能允许等待获取(共享或独占)成功; 否则为false
        异常
        IllegalMonitorStateException - 如果释放将此同步器置于非法状态。 必须以一致的方式抛出此异常才能使同步正常工作。
        UnsupportedOperationException - 如果不支持共享模式
      • acquire

        public final void acquire​(int arg)
        以独占模式获取,忽略中断。 通过至少调用一次tryAcquire(int)实现 ,返回成功。 否则线程排队,可能反复阻塞和解除阻塞,调用tryAcquire(int)直到成功。 该方法可用于实现方法Lock.lock()
        参数
        arg - 获取参数。 此值传达到tryAcquire(int)但未解释,可以表示您喜欢的任何内容。
      • acquireInterruptibly

        public final void acquireInterruptibly​(int arg)
                                        throws InterruptedException
        以独占模式获取,如果被中断则中止。 通过首先检查中断状态,然后至少调用一次tryAcquire(int)来实现 ,返回成功。 否则,线程排队,可能反复阻塞和解除阻塞,调用tryAcquire(int)直到成功或线程被中断。 该方法可用于实现方法Lock.lockInterruptibly()
        参数
        arg - 获取参数。 此值传达到tryAcquire(int)但未解释,可以表示您喜欢的任何内容。
        异常
        InterruptedException - 如果当前线程被中断
      • tryAcquireNanos

        public final boolean tryAcquireNanos​(int arg,
                                             long nanosTimeout)
                                      throws InterruptedException
        尝试以独占模式获取,如果中断则中止,如果超过给定超时则失败。 通过首先检查中断状态,然后至少调用一次tryAcquire(int)来实现 ,返回成功。 否则,线程排队,可能反复阻塞和解除阻塞,调用tryAcquire(int)直到成功或线程中断或超时结束。 该方法可用于实现方法Lock.tryLock(long, TimeUnit)
        参数
        arg - 获取参数。 此值传达到tryAcquire(int)但未解释,可以表示您喜欢的任何内容。
        nanosTimeout - 等待的最大纳秒数
        结果
        true如果获得; false若超时时间
        异常
        InterruptedException - 如果当前线程被中断
      • acquireShared

        public final void acquireShared​(int arg)
        以共享模式获取,忽略中断。 首先调用至少一次tryAcquireShared(int)实现 ,返回成功。 否则线程排队,可能反复阻塞和解除阻塞,调用tryAcquireShared(int)直到成功。
        参数
        arg - 获取参数。 此值传达到tryAcquireShared(int)但未解释,可以表示您喜欢的任何内容。
      • acquireSharedInterruptibly

        public final void acquireSharedInterruptibly​(int arg)
                                              throws InterruptedException
        以共享模式获取,如果中断则中止。 通过首先检查中断状态,然后至少调用一次tryAcquireShared(int)来实现 ,返回成功。 否则,线程排队,可能反复阻塞和解除阻塞,调用tryAcquireShared(int)直到成功或线程被中断。
        参数
        arg - 获取参数。 此值传达给tryAcquireShared(int)但未解释,可以代表您喜欢的任何内容。
        异常
        InterruptedException - 如果当前线程被中断
      • tryAcquireSharedNanos

        public final boolean tryAcquireSharedNanos​(int arg,
                                                   long nanosTimeout)
                                            throws InterruptedException
        尝试以共享模式获取,如果中断则中止,如果超过给定超时则失败。 首先检查中断状态,然后至少调用一次tryAcquireShared(int) ,成功返回。 否则,线程排队,可能反复阻塞和解除阻塞,调用tryAcquireShared(int)直到成功或线程中断或超时结束。
        参数
        arg - 获取参数。 此值传达到tryAcquireShared(int)但未解释,可以表示您喜欢的任何内容。
        nanosTimeout - 等待的最大纳秒数
        结果
        true如果获得; false若超时
        异常
        InterruptedException - 如果当前线程被中断
      • releaseShared

        public final boolean releaseShared​(int arg)
        以共享模式发布。 如果tryReleaseShared(int)返回true,则通过解除阻塞一个或多个线程实现。
        参数
        arg - 发布参数。 此值传达给tryReleaseShared(int)但未解释并且可以表示您喜欢的任何内容。
        结果
        tryReleaseShared(int)返回的值
      • hasQueuedThreads

        public final boolean hasQueuedThreads()
        查询是否有任何线程正在等待获取。 请注意,由于中断和超时导致的取消可能随时发生,因此true返回不保证任何其他线程将获得。
        结果
        true是否有其他线程等待获取
      • hasContended

        public final boolean hasContended()
        查询是否有任何线程争用获取此同步器; 也就是说,如果获取方法曾被阻止。

        在此实现中,此操作以恒定时间返回。

        结果
        true如果曾经有过争论
      • getFirstQueuedThread

        public final Thread getFirstQueuedThread()
        返回队列中的第一个(等待时间最长的)线程,如果当前没有线程排队,则null

        在此实现中,此操作通常以恒定时间返回,但如果其他线程同时修改队列,则可能在争用时迭代。

        结果
        队列中的第一个(等待时间最长的)线程,如果当前没有线程排队, null
      • isQueued

        public final boolean isQueued​(Thread thread)
        如果给定线程当前已排队,则返回true。

        此实现遍历队列以确定给定线程的存在。

        参数
        thread - 主题
        结果
        true如果给定线程在队列中
        异常
        NullPointerException - 如果线程为空
      • hasQueuedPredecessors

        public final boolean hasQueuedPredecessors()
        查询是否有任何线程等待获取的时间长于当前线程。

        调用此方法相当于(但可能更有效):

           getFirstQueuedThread() != Thread.currentThread() && hasQueuedThreads() 

        请注意,由于中断和超时导致的取消可能随时发生,因此true返回并不保证某些其他线程将在当前线程之前获取。 同样,由于队列为空,此方法返回false后,另一个线程可能会赢得一场竞选。

        此方法旨在由公平同步器使用以避免barging 这种同步器的tryAcquire(int)方法应返回false ,如果此方法返回true ,则其tryAcquireShared(int)方法应返回负值(除非这是可重入获取)。 例如,公平,可重入,独占模式同步器的tryAcquire方法可能如下所示:

           protected boolean tryAcquire(int arg) { if (isHeldExclusively()) { // A reentrant acquire; increment hold count return true; } else if (hasQueuedPredecessors()) { return false; } else { // try to acquire normally } } 
        结果
        true如果在当前线程之前有一个排队的线程, false如果当前线程位于队列的头部或队列为空
        从以下版本开始:
        1.7
      • getQueueLength

        public final int getQueueLength()
        返回等待获取的线程数的估计值。 该值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态更改。 此方法设计用于监视系统状态,而不是用于同步控制。
        结果
        估计等待获取的线程数
      • getQueuedThreads

        public final Collection<Thread> getQueuedThreads()
        返回包含可能正在等待获取的线程的集合。 因为实际的线程集可能在构造此结果时动态更改,所以返回的集合仅是尽力而为的估计。 返回集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛监控设施的子类。
        结果
        线程集合
      • getExclusiveQueuedThreads

        public final Collection<Thread> getExclusiveQueuedThreads()
        返回包含可能等待以独占模式获取的线程的集合。 它具有与getQueuedThreads()相同的属性,只是它只返回由于独占获取而等待的那些线程。
        结果
        线程集合
      • getSharedQueuedThreads

        public final Collection<Thread> getSharedQueuedThreads()
        返回包含可能正在等待以共享模式获取的线程的集合。 它具有与getQueuedThreads()相同的属性,只是它只返回由于共享获取而等待的那些线程。
        结果
        线程集合
      • toString

        public String toString()
        返回标识此同步器的字符串及其状态。 括号中的状态包括字符串"State ="后跟当前值getState() ,以及"nonempty""empty"具体取决于队列是否为空。
        重写:
        toStringObject
        结果
        标识此同步器的字符串及其状态
      • hasWaiters

        public final boolean hasWaiters​(AbstractQueuedSynchronizer.ConditionObject condition)
        查询是否有任何线程正在等待与此同步器关联的给定条件。 请注意,由于超时和中断可能随时发生, true返回并不能保证未来的signal会唤醒任何线程。 该方法主要用于监视系统状态。
        参数
        condition - 条件
        结果
        true如果有任何等待线程
        异常
        IllegalMonitorStateException - 如果未保留独占同步
        IllegalArgumentException - 如果给定条件与此同步器无关
        NullPointerException - 如果条件为null
      • getWaitQueueLength

        public final int getWaitQueueLength​(AbstractQueuedSynchronizer.ConditionObject condition)
        返回与此同步器关联的给定条件上等待的线程数的估计值。 请注意,由于超时和中断可能在任何时间发生,因此估计仅用作实际服务员数量的上限。 此方法设计用于监视系统状态,而不是用于同步控制。
        参数
        condition - 条件
        结果
        估计的等待线程数
        异常
        IllegalMonitorStateException - 如果未保留独占同步
        IllegalArgumentException - 如果给定条件与此同步器无关
        NullPointerException - 如果条件为null