AbstractQueuedSynchronizer解读

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

            子类应定义为非公共内部助手类,用于实现其封闭类的同步属性。 AbstractQueuedSynchronizer类不实现任何同步接口。 相反,它定义了一些方法,如acquireInterruptibly(int) ,能够恰当地经过调用具体的锁和相关同步器来实现其公共方法。api

    此类支持默认独占模式和共享模式。 当以独占模式获取时,尝试经过其余线程获取不能成功。 多线程获取的共享模式可能(但不须要)成功。 除了在机械意义上,这个类不理解这些差别,当共享模式获取成功时,下一个等待线程(若是存在)也必须肯定它是否也能够获取。 在不一样模式下等待的线程共享相同的FIFO队列。 一般,实现子类只支持这些模式之一,可是二者均可以在ReadWriteLock发挥做用 。 仅支持独占或仅共享模式的子类不须要定义支持未使用模式的方法。安全

    这个类定义的嵌套AbstractQueuedSynchronizer.ConditionObject可用于做为一类Condition由子类支持独占模式用于该方法的实施isHeldExclusively()报告是否同步排他相对于保持在当前线程,方法release(int)与当前调用getState()值彻底释放此目的,和acquire(int) ,给定此保存的状态值,最终将此对象恢复到其先前获取的状态。 AbstractQueuedSynchronizer方法将建立此类条件,所以若是不能知足此约束,请勿使用该约束。 AbstractQueuedSynchronizer.ConditionObject的行为固然取决于其同步器实现的语义。数据结构

    该类为内部队列提供检查,检测和监控方法,以及条件对象的相似方法。 这些能够根据须要导出到类中,使用AbstractQueuedSynchronizer进行同步机制。多线程

    此类的序列化仅存储底层原子整数维持状态,所以反序列化对象具备空线程队列。 须要可序列化的典型子类将定义一个readObject方法,能够将其恢复为readObject时的已知初始状态。框架

    用法

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

    每一个这些方法默认抛出 UnsupportedOperationException 。 这些方法的实现必须是线程安全的,一般应该是短的而不是阻止的。 定义这些方法是 惟一支持使用此类的方法。 全部其余方法都被声明为 final ,由于它们不能独立变化。

    您还能够找到来自继承的方法AbstractOwnableSynchronizer有用跟踪线程拥有独家同步的。 咱们鼓励您使用它们 - 这样可使监控和诊断工具帮助用户肯定哪些线程持有锁定。工具

    即便这个类基于内部FIFO队列,它也不会自动执行FIFO采集策略。 排他同步的核心形式以下:ui

    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来禁用驳船,从而提供一个合理的 FIFO采购订单。 特别地,最公平同步器能够定义tryAcquire返回false若是hasQueuedPredecessors() (具体地设计成由公平同步器中使用的方法)返回true 。 其余变化是可能的。

    吞吐量和可扩展性一般对于默认的驳船(也称为贪心放弃车队避免 )战略来讲是最高的。 虽然这不能保证是公平的或无饥饿的,但较早排队的线程在稍后排队的线程以前被容许从新侦听,而且每次从新提供对于传入线程成功的机会。 此外,虽然获取在一般意义上不“旋转”,可是在阻止以前它们能够执行多个tryAcquire 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 { // Reports whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // 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 (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Provides a Condition 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.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若是成功。 False return表示实际值不等于预期值。

      • tryAcquire

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

        该方法老是由执行获取的线程调用。 若是此方法报告失败,则获取方法可能将线程排队(若是还没有排队),直到被其余线程释放为止。 这能够用于实现方法Lock.tryLock()

        默认实现会抛出UnsupportedOperationException

        参数

        arg - 获取的论据。 该值始终是传递给获取方法的值,或者是进入条件等待时保存的值。 该值不然没法解释,能够表明您喜欢的任何内容。

        结果

        true若是成功。 一旦成功,这个对象就被收购了。

        异常

        IllegalMonitorStateException - 若是获取将该同步器置于非法状态。 必须以一致的方式抛出此异常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持独占模式

      • tryRelease

        protected boolean tryRelease(int arg)
        尝试设置状态以独占模式反映版本。

        该方法老是由执行释放的线程调用。

        默认实现抛出UnsupportedOperationException

        参数

        arg - 释放参数。 该值始终是传递给release方法的值,或者进入条件等待时的当前状态值。 该值不然没法解释,能够表明您喜欢的任何内容。

        结果

        true若是此对象如今处于彻底释放状态,那么任何等待的线程均可能尝试获取; 和false其余。

        异常

        IllegalMonitorStateException - 若是释放将使此同步器处于非法状态。 必须以一致的方式抛出此异常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持独占模式

      • tryAcquireShared

        protected int tryAcquireShared(int arg)
        尝试以共享模式获取。 该方法应该查询对象的状态是否容许在共享模式下获取该对象,若是是这样,就能够获取它。

        该方法老是由执行获取的线程调用。 若是此方法报告失败,则获取方法可能将线程排队(若是还没有排队),直到被其余线程释放为止。

        默认实现抛出UnsupportedOperationException

        参数

        arg - 获取的论据。 该值始终是传递给获取方法的值,或者是进入条件等待时保存的值。 该值不然没法解释,能够表明您喜欢的任何内容。

        结果

        失败的负值 若是在共享模式下获取成功但没有后续共享模式获取能够成功,则为零; 而且若是以共享模式获取成功而且随后的共享模式获取可能成功,则为正值,在这种状况下,后续等待线程必须检查可用性。 (支持三种不一样的返回值使得这种方法能够在仅获取有时只能彻底执行的上下文中使用。)成功后,该对象已被获取。

        异常

        IllegalMonitorStateException - 若是获取将该同步器置于非法状态。 必须以一致的方式抛出此异常,以使同步正常工做。

        UnsupportedOperationException - 若是不支持共享模式

      • tryReleaseShared

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

        该方法老是由执行释放的线程调用。

        默认实现会抛出UnsupportedOperationException

        参数

        arg - 释放参数。 该值始终是传递给release方法的值,或者进入条件等待时的当前状态值。 该值不然没法解释,能够表明您喜欢的任何内容。

        结果

        true若是这种共享模式的释放可能容许等待获取(共享或排他)成功; false 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 - 当前线程是否中断

      • release

        public final boolean release(int arg)
        以专属模式发布。 若是 tryRelease(int)返回true,则经过解除阻塞一个或多个线程 实现。 该方法能够用于实现方法 Lock.unlock()

        参数

        arg - 释放参数。 这个值被传达到tryRelease(int)可是没有被解释,能够表明你喜欢的任何东西。

        结果

        tryRelease(int)返回的值

      • 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()
        查询任何线程是否等待获取。 请注意,因为中断和超时可能会随时发生 truetrue返回不能保证任何其余线程将得到。

        在这个实现中,这个操做返回恒定的时间。

        结果

        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 ,所以true返回不能保证其余一些线程将在当前线程以前获取。 一样,因为队列为空,这个方法已经返回false ,所以另外一个线程可能会赢得比赛排入队列。

        该方法被设计为由一个公平的同步器使用,以免barging 。 这样一个同步器的tryAcquire(int)方法应该返回false ,而且它的tryAcquireShared(int)方法应该返回一个负值,若是这个方法返回true (除非这是一个可重入的获取)。 例如, 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"取决于队列是否为空。

        重写:

        toString在类别 Object

        结果

        识别此同步器的字符串以及其状态

      • hasWaiters

        public final boolean hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition)
        查询任何线程是否等待与此同步器相关联的给定条件。 请注意,因为超时和中断可能随时发生, true返回不能保证将来的 signal将唤醒任何线程。 该方法主要用于监视系统状态。

        参数

        condition - 条件

        结果

        true若是有任何等待线程

        异常

        IllegalMonitorStateException - 若是不保留独占同步

        IllegalArgumentException - 若是给定的条件与此同步器无关

        NullPointerException - 若是条件为空

      • getWaitQueueLength

        public final int getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition)
        返回等待与此同步器相关联的给定条件的线程数量的估计。 请注意,因为超时和中断可能在任什么时候间发生,估计仅做为实际服务员人数的上限。 该方法设计用于监视系统状态,不用于同步控制。

        参数

        condition - 条件

        结果

        估计等待线程数

        异常

        IllegalMonitorStateException - 若是不保留独占同步

        IllegalArgumentException - 若是给定的条件与该同步器没有关联

        NullPointerException - 若是条件为空

相关文章
相关标签/搜索