当前位置: 首页> 教育> 幼教 > 广告设计公司税务筹划_青岛手机建站模板_网络营销的目的是_软文写作

广告设计公司税务筹划_青岛手机建站模板_网络营销的目的是_软文写作

时间:2025/7/13 4:46:12来源:https://blog.csdn.net/qq_39288456/article/details/143350889 浏览次数:0次
广告设计公司税务筹划_青岛手机建站模板_网络营销的目的是_软文写作

前言


 相关系列

  • 《Java & Condition & 目录》
  • 《Java & AQS & 目录》
  • 《Java & Condition/AQS & ConditionObject & 源码》
  • 《Java & Condition/AQS & ConditionObject & 总结》
  • 《Java & Condition/AQS & ConditionObject & 问题》
     

 涉及内容

  • 《Java & Condition & 总结》
  • 《Java & AQS & 总结》
  • 《Java & Lock & LockSupport & 总结》
     
     

源码


    /*** Condition implementation for a {@link AbstractQueuedSynchronizer} serving as the basis of a {@link Lock}* implementation.* AQS的条件实现用于充当锁实现的基础。* <p>* Method documentation for this class describes mechanics, not behavioral specifications from the point of view of* Lock and Condition users. Exported versions of this class will in general need to be accompanied by documentation* describing condition semantics that rely on those of the associated {@code AbstractQueuedSynchronizer}.* 该类的方法文档从锁和条件用户的角度描述了机制,而不是行为规范。这个类的导出版本通常需要附带描述依赖于相* 关AbstractQueuedSynchronizer的条件语义的文档。* <p>* This class is Serializable, but all fields are transient, so deserialized conditions have no waiters.* 该类是序列化的,但所有字段被修饰了transient,所以反序列化的条件没有等待者。** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 条件对象* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* ----* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/public class ConditionObject implements Condition, Serializable {private static final long serialVersionUID = 1173984872572414699L;/*** First node of condition queue.* 条件队列的头节点** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 首个等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 持有当前条件队列中首个节点的引用* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/private transient Node firstWaiter;/*** Last node of condition queue.* 条件队列的最后节点** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 最后等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 持有当前条件队列中最后节点的引用* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/private transient Node lastWaiter;/*** Creates a new {@code ConditionObject} instance.* 创建一个新条件对象实例** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 条件对象* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 创建条件对象* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/public ConditionObject() {}// Internal methods// 内部方法/*** Adds a new waiter to wait queue.* 新增一个新等待者至等待队列** @return its new wait node 它sd的新等待节点* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 新增条件等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 将当前封装为节点并加入当前条件对象的条件队列中* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会获取[最后等待者],如果[最后等待者]存在且已被取消则触发清理条件队列中的所有取消节点,随后* 重新获取[最后等待者]。注意,由于取消的并发性,即使在经历过清理后也无法保证条件队列中不存在取消节点,因* 为节点可能在清理的过程中被取消,甚至于重新获取的[最后等待者]依然是一个取消节点...清理的目的是为了将取消* 节点的数量控制在一个先对较低的数量级。* ---- 获取[最后等待着]后,方法会基于当前线程创建一个[等待状态]为CONDITION(-2:条件)的节点,并将之加入到* 条件队列中成为[最后等待者],如果当前条件队列中没有其它节点的话则其还需要被设置为[首个等待者]。该过程不* 需要CAS的保护,因为该操作只有以独占模式获取[状态]的当前线程才可以操作,因此不会出现并发。*/private Node addConditionWaiter() {// ---- 方法首先会获取[最后等待者],如果[最后等待者]存在且已被取消则触发清理条件队列中的所有取消节点,随// 后重新获取[最后等待者]。注意,由于取消的并发性,即使在经历过清理后也无法保证条件队列中不存在取消节点,// 因为节点可能在清理的过程中被取消,甚至于重新获取的[最后等待者]依然是一个取消节点...清理的目的是为了将// 取消节点的数量控制在一个先对较低的数量级。Node t = lastWaiter;if (t != null && t.waitStatus != Node.CONDITION) {unlinkCancelledWaiters();t = lastWaiter;}// ---- 获取[最后等待着]后,方法会基于当前线程创建一个[等待状态]为CONDITION(-2:条件)的节点,并将之加入// 到条件队列中成为[最后等待者],如果当前条件队列中没有其它节点的话则其还需要被设置为[首个等待者]。该过// 程不需要CAS的保护,因为该操作只有以独占模式获取[状态]的当前线程才可以操作,因此不会出现并发。Node node = new Node(Thread.currentThread(), Node.CONDITION);if (t == null) {firstWaiter = node;} else {t.nextWaiter = node;}lastWaiter = node;return node;}/*** Removes and transfers nodes until hit non-cancelled one or null. Split out from signal in part to encourage* compilers to inline the case of no waiters.* 移除并迁移节点直至碰撞未取消节点或所有节点都已被移除/迁移。从信号中部分爆发以鼓励供应商去内联无等待者* 的情况。** @param first (non-null) the first node on condition queue 条件队列中的首个节点* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 执行唤醒* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 唤醒在当前条件对象中等待的首个线程。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 指定节点为条件队列的[首个等待者],方法首先指定节点的[后继等待者]设置为新[首个等待者],该行为相当于* 将指定节点从条件队列中移除。随后如果新[首个等待者]为null,则说明条件队列中已无等待者,再将[最后等待者]* 赋值为null。完成对指定等待者的移除后,方法会将其[后继等待者]赋值为null,相当于断开了指定等待者与条件队* 列的关联。* ----- 接下来方法会调用transferForSignal(Node node)方法唤醒指定等待者[线程],如果因为等待者已被取消而唤醒* 失败,则会将新[首个等待者]作为新指定等待者重复执行,直至成功唤醒[首个等待者][线程]为止。*/private void doSignal(Node first) {// ---- 指定节点为条件队列的[首个等待者],方法首先指定节点的[后继等待者]设置为新[首个等待者],该行为相当// 于将指定节点从条件队列中移除。随后如果新[首个等待者]为null,则说明条件队列中已无等待者,再将[最后等// 待者]赋值为null。完成对指定等待者的移除后,方法会将其[后继等待者]赋值为null,相当于断开了指定等待者与// 条件队列的关联。// ----- 接下来方法会调用transferForSignal(Node node)方法唤醒指定等待者[线程],如果因为等待者已被取消而唤// 醒失败,则会将新[首个等待者]作为新指定等待者重复执行,直至成功唤醒[首个等待者][线程]为止。do {if ((firstWaiter = first.nextWaiter) == null) {lastWaiter = null;}first.nextWaiter = null;} while (!transferForSignal(first) && (first = firstWaiter) != null);}/*** Removes and transfers all nodes.* 移除并迁移所有的节点。** @param first (non-null) the first node on condition queue 条件队列中的首个节点* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 执行全唤醒* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 唤醒在当前条件对象中等待的所有线程。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会将的[首个/最后等待者]赋值为null,该行为的作用是将所有的等待者从条件队列中移除。随后方法会* 遍历等待者链并依次对所有的[线程]都进行唤醒,直至将除取消等待者以外的所有[线程]都唤醒为止。*/private void doSignalAll(Node first) {// ---- 方法首先会将的[首个/最后等待者]赋值为null,该行为的作用是将所有的等待者从条件队列中移除。随后方// 法会遍历等待者链并依次对所有的[线程]都进行唤醒,直至将除取消等待者以外的所有[线程]都唤醒为止。lastWaiter = firstWaiter = null;do {Node next = first.nextWaiter;first.nextWaiter = null;transferForSignal(first);first = next;} while (first != null);}/*** Unlinks cancelled waiter nodes from condition queue. Called only while holding lock. This is called when* cancellation occurred during condition wait, and upon insertion of a new waiter when lastWaiter is seen to have* been cancelled. This method is needed to avoid garbage retention in the absence of signals. So even though it may* require a full traversal, it comes into play only when timeouts or cancellations occur in the absence of signals.* It traverses all nodes rather than stopping at a particular target to unlink all pointers to garbage nodes* without requiring many re-traversals during cancellation storms.* 从条件队列中断开已取消等待节点的链接。只在持有锁期间被调用。当取消在条件等待期间发生,以及一个新等待* 者在最后等待者看起来已被取消时插入时调用。该方法需要避免垃圾在缺失信号时遗留。所以即使它可能需要一个完* 整的遍历,但也只会在缺失信号时在超时或取消发生时开始运行。它会遍历所有的节点而不是在指定目标处停止以断* 开所有垃圾节点的指针而不需要在取消爆发式多次取消。** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 断开已取消的等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 清理当前条件对象中条件队列的所有取消节点* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会获取[首个等待者],随后完整遍历整个条件队列,并移除其中所有已取消的节点。*/private void unlinkCancelledWaiters() {// ---- 方法首先会获取[首个等待者],随后完整遍历整个条件队列,并移除其中所有已取消的节点。Node t = firstWaiter;Node trail = null;while (t != null) {Node next = t.nextWaiter;if (t.waitStatus != Node.CONDITION) {t.nextWaiter = null;if (trail == null) {firstWaiter = next;} else {trail.nextWaiter = next;}if (next == null) {lastWaiter = trail;}} else {trail = t;}t = next;}}// public methods// 公共方法/*** Moves the longest-waiting thread, if one exists, from the wait queue for this condition to the wait queue for the* owning lock.* 如果存在,从当前条件的等待队列中移动等待时间最长的线程至关联的同步队列。** @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}*                                      非法监视状态异常:如果isHeldExclusively()返回false* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 断开已取消的等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 清理当前条件对象中条件队列的所有取消节点* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。* ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线程]中* 等待时间最长的。*/@Overridepublic final void signal() {// ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。if (!isHeldExclusively()) {throw new IllegalMonitorStateException();}// ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线// 程]中等待时间最长的。Node first = firstWaiter;if (first != null) {doSignal(first);}}/*** Moves all threads from the wait queue for this condition to the wait queue for the owning lock.* 从条件队列中移动所有的线程至同步队列中。** @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}*                                      非法监视状态异常:如果isHeldExclusively()返回false* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 断开已取消的等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 清理当前条件对象中条件队列的所有取消节点* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。* ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线程]中* 等待时间最长的。*/@Overridepublic final void signalAll() {// ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。if (!isHeldExclusively()) {throw new IllegalMonitorStateException();}// ---- 如果当前线程是独占AQS的线程,唤醒条件队列中的所有等待者[线程]。Node first = firstWaiter;if (first != null) {doSignalAll(first);}}/*** Implements uninterruptible condition wait.* 实现不可中断的条件等待* <ol>* <li> Save lock state returned by {@link #getState}.* 保存通过getState()方法返回的锁状态。* <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.* 随着保存的状态作为参数调用release()方法,如果失败则抛出非法监视状态异常。* <li> Block until signalled.* 阻塞直至收到信号。* <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.* 通过调用随着保存的状态作为参数调用指定的版本来进行重获取。* </ol>** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 等待(不可中断)* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 令当前线程释放所有状态后在当前条件对象中等待,直至被唤醒后重新获取释放的所有状态。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会将当前独占线程封装为等待着加入条件队列中,随后一次性将这些[状态]全部释放,该行为意味着当* 前独占线程解除了对AQS的独占,也意味着会有其它线程对[状态]进行竞争。* ---- 随后方法会判断当前等待者是否位于同步队列中,等待者会位于同步队列中说明有独占AQS的线程对之进行了迁* 移并对[线程]执行了唤醒。如果不位于同步队列中,说明当前等待者依然位于条件队列中,因此其[线程]需要进入有* 限/无限等待状态。* ---- 进入有限/无限等待状态的等待者[线程]可能因为中断而被唤醒,由于当前方法在设计上不可被中断,即不会响* 应中断,因此被唤醒后的等待者[线程]不会抛出中断异常,而是判断等待者是否位于同步队列中。如果不是则再次进* 入有限/无限等待状态;否则说明其以被再次加入对[状态]的竞争。* ---- 等待者加入同步队列后[线程]会执行对[状态]的获取。此次获取与之前不同,会直接一次获取释放的所有[状态],* 获取成功后如果发现当前线程曾经经历过中断,则便将[线程]的中断状态设置为true。*/@Overridepublic final void awaitUninterruptibly() {// ---- 方法首先会将当前独占线程封装为等待着加入条件队列中,随后一次性将这些[状态]全部释放,该行为意味// 着当前独占线程解除了对AQS的独占,也意味着会有其它线程对[状态]进行竞争。Node node = addConditionWaiter();int savedState = fullyRelease(node);// ---- 随后方法会判断当前等待者是否位于同步队列中,等待者会位于同步队列中说明有独占AQS的线程对之进行// 了迁移并对[线程]执行了唤醒。如果不位于同步队列中,说明当前等待者依然位于条件队列中,因此其[线程]需// 要进入有限/无限等待状态。// ---- 进入有限/无限等待状态的等待者[线程]可能因为中断而被唤醒,由于当前方法在设计上不可被中断,即不会// 响应中断,因此被唤醒后的等待者[线程]不会抛出中断异常,而是判断等待者是否位于同步队列中。如果不是则// 再次进入有限/无限等待状态;否则说明其以被再次加入对[状态]的竞争。boolean interrupted = false;while (!isOnSyncQueue(node)) {LockSupport.park(this);if (Thread.interrupted()) {interrupted = true;}}// ---- 等待者加入同步队列后[线程]会执行对[状态]的获取。此次获取与之前不同,会直接一次获取释放的所有[状// 态],获取成功后如果发现当前线程曾经经历过中断,则便将[线程]的中断状态设置为true。if (acquireQueued(node, savedState) || interrupted) {selfInterrupt();}}/** For interruptible waits, we need to track whether to throw InterruptedException, if interrupted while blocked on* condition, versus reinterrupt current thread, if interrupted while blocked waiting to re-acquire.* 关于可中断等待,我们需要追踪是否抛出中断异常,如果在条件阻塞中被中断,与再次中断当前线程相比,如果在阻* 塞等待期间重获取则中断。*//*** Mode meaning to reinterrupt on exit from wait* 模式意味着从等待中退出时重中断** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 重中断* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 该标志意味着当线程因为中断而唤醒时需要保留中断状态* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/private static final int REINTERRUPT = 1;/*** Mode meaning to throw InterruptedException on exit from wait* 模式意味着从等待中退出时抛出中断异常** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 重中断* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 该标志意味着当线程因为中断而唤醒时需要抛出中断异常* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/private static final int THROW_IE = -1;/*** Checks for interrupt, returning THROW_IE if interrupted before signalled, REINTERRUPT if after signalled, or 0* if not interrupted.* 检查中断,如果在被信号通知前中断则返回THROW_IE,如果在信号通知后中断则返回REINTERRUPT,或者如果未* 中断则返回0。** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 检查等待期间中断* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 检查当前线程是否在等待期间被中断,如果在唤醒前被中断则返回THROW_IE(-1);如果在唤醒后被中断则返回* REINTERRUPT(1);如果未中断则返回0。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ----*/private int checkInterruptWhileWaiting(Node node) {// ---- 方法首先会令当前线程相应中断,如果当前线程未被中断则直接返回0;否则继续return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;}/*** Throws InterruptedException, reinterrupts current thread, or does nothing, depending on mode.* 根据模式抛出异常,重中断当前线程或什么也不做。** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 在等待后记录中断* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 根据线程的唤醒方式抛出异常、自我中断或什么也不做。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断指定中断模式是否为抛出THROW_IE,是则说明当前线程是因为中断而被唤醒,或者更准确的说* '是自身将节点的[等待状态]由Condition(-2:条件)CAS赋值为0;因此需要抛出中断异常;而如果指定中断模式为* REINTERRUPT,则意味着当前线程在被信号唤醒后又遭遇了中断,因此需要还原中断状态;而如果都不是,则意味* 着当前线程是被信号唤醒且整个过程中都未曾经历过中断,因此什么也不做。*/private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {if (interruptMode == THROW_IE) {// 直接抛出异常。throw new InterruptedException();} else if (interruptMode == REINTERRUPT) {// 自我中断。selfInterrupt();}}/*** Implements interruptible condition wait.* 实现可中断条件等待。* <ol>* <li> If current thread is interrupted, throw InterruptedException.* 如果线程已被中断,抛出中断异常。* <li> Save lock state returned by {@link #getState}.* 保存通过getState()方法返回的锁状态。* <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.* 随着保存的状态作为参数调用release()方法,如果失败则抛出非法状态异常。* <li> Block until signalled or interrupted.* 阻塞直至被通知或被中断。* <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.* 通过随保存的状态作为参数调用acquire()方法的指定版本重获取。* <li> If interrupted while blocked in step 4, throw InterruptedException.* 如果在阻塞至步骤四时被中断则抛出中断异常。* </ol>** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 等待* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 令当前线程以独占模式释放所有的状态后在当前条件对象中无限等待,直至因为信号/中断而被唤醒并重新获取之前* 释放的所有状态。在成功获取状态后,如果存在中断并发的情况下,如果当前线程因为信号而唤醒则需要保留中断* 状态;否则抛出中断异常。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。因为当前方法的设定就是要在中断时抛出中断* 异常。随后方法会将当前线程封装为独占节点加入条件队列中,并释放所有的[状态],这一步之后其它线程便可以* 对[状态]进行竞争。* ---- 这之后方法会循环判断独占节点是否位于同步队列中,条件队列中的独占节点会位于同步队列中是因为其会被* 当前线程或AQS独占线程迁移。如果是首次判断发现独占节点位于同步队列中,由于此时当前线程还未进入有限/* 无限等待状态,因此独占节点只可能是被AQS独占线程迁移。而如果是非首次判断发现独占节点位于同步队列中,* 则可能是被当前线程或AQS独占线程迁移。* ---- 独占节点位于同步队列中意味着当前线程已重新参与对[状态]的竞争,因此如果独占节点位于同步队列中则当* 前线程应该执行等待流程已获取[状态]。而如果独占节点不位于同步队列中则意味着当前线程需要进入有限/无限* 等待状态直到被主动/被动的唤醒。被唤醒的当前线程会判断自身因为什么而唤醒,如果是因为中断而唤醒,则当* 前方法会抛出中断异常;而如果是因为信号而唤醒,则当前线程并不会做什么。但是如果两种唤醒方式出现并发,* 则以成功将独占节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0的唤醒方式为准。* ---- 事实上,这里会进行独占节点是否位于同步队列的判断就是一个很令人疑惑的问题,因为理论上只要当前线程* 进入有限/无限等待状态中,则无论是因为信号/中断/超时而被唤醒都意味着其必然会被迁移至同步队列中。其中* 信号唤醒会在AQS独占线程将独占节点迁移至队列后执行,而中断/超时唤醒发生时虽然独占节点依然处于条件队* 列中,但后续也会立即执行,即当前线程必然会在判断独占节点是否位于同步队列之前将之迁移至同步队列中,因* 此从逻辑上来说似乎完全没有判断的必要,更不要说还是循环判断。* ---- 循环判断独占节点是否位于同步队列中的根本目的是为了避免虚假唤醒,即避免当前线程在条件为达成的情况* 下被唤醒,而所谓的条件自然是独占节点位于同步队列中。事实上,正常情况下当前线程因为信号/中断/超时的原* 因被唤醒是不会出现虚拟唤醒的,即正常情况下当前线程被唤醒后独占节点必然已经处于同步队列中,具体原因上* 文已经上述过。而之所以会出现虚拟唤醒的情况是由于外部条件的影响而使得当前线程无法进入有限/无限等待状* 态或被以外唤醒,而这个就与AQS对线程使用的等待/唤醒工具类LockSupport的机制有关。* ---- LockSupport通过park/unpark方法等待/唤醒线程,但与常规等待/唤醒不同的是LockSupport存在许可的概念。* 线程最多可以持有一个许可,当线程持有的许可数量 < 0时线程就会进入有限/无限等待状态,因此park/unpark方* 法本质上就是在递减/递增线程的许可。线程的默认许可数为0,因此该状态下当对其执行park方法时线程就会因为* 许可数 < 0而进入有限/无限等待状态,而在当对其执行unpark()方法时就会使得许可数为0而唤醒。这种情况属于* 正常思维下的标准流程,但除此之外还存在一些相对不标准的流程,即如果先对线程执行被unpark()方法而使得许* 可数量为1,则在对其执行park()方法时也只能使其为许可数量为0而无法进入有限/无限等待状态。而这就是造成虚* 假唤醒的根本原因。* ---- 虚假唤醒并不是AQS内部对线程执行LockSupport.park/unpark方法导致的,因为上文已经说过信号唤醒只有在* 成功将独占节点迁移至同步队列后才会执行,因此这种情况当前线程如论时具备许可而无法进入有限/无限等待状态* 还是被唤醒都必然保证了独占节点位于同步队列中,因此虚假唤醒的情况实际上是由外部的其它线程对当前线程执* 行LockSupport.unpark()方法造成的。这种LockSupport.unpark()方法的执行不受AQS内部逻辑的控制,因此就可能* 导致线程在独占节点未迁移至同步队列的情况下无法进入有限/无限等待状态或被唤醒。并且由于这种方法的次数和* 时机都无法被预知,因此一次判断是不够的,必须循环判断到达成条件为止。循环判断的存在使得外部唤醒无论被* 执行了多少次都能够保证线程不会在为达成条件的情况下尝试重新能获取状态,即使其可能只是在不断的自旋而不* 是进入有限/无限状态。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占* 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,* 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意* 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不* 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占* 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。* ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断。*/@Overridepublic final void await() throws InterruptedException {// ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。因为当前方法的设定就是要在中断时抛出中// 断异常。随后方法会将当前线程封装为独占节点加入条件队列中,并释放所有的[状态],这一步之后其它线程便// 可以对[状态]进行竞争。if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);int interruptMode = 0;// ---- 这之后方法会循环判断独占节点是否位于同步队列中,条件队列中的独占节点会位于同步队列中是因为其会// 被当前线程或AQS独占线程迁移。如果是首次判断发现独占节点位于同步队列中,由于此时当前线程还未进入有// 限/无限等待状态,因此独占节点只可能是被AQS独占线程迁移。而如果是非首次判断发现独占节点位于同步队// 列中,则可能是被当前线程或AQS独占线程迁移。// ---- 独占节点位于同步队列中意味着当前线程已重新参与对[状态]的竞争,因此如果独占节点位于同步队列中则// 当前线程应该执行等待流程已获取[状态]。而如果独占节点不位于同步队列中则意味着当前线程需要进入有限/// 无限等待状态直到被主动/被动的唤醒。被唤醒的当前线程会判断自身因为什么而唤醒,如果是因为中断而唤醒,// 则当前方法会抛出中断异常;而如果是因为信号而唤醒,则当前线程并不会做什么。但是如果两种唤醒方式出现// 并发,则以成功将独占节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0的唤醒方式为准。// ---- 事实上,这里会进行独占节点是否位于同步队列的判断就是一个很令人疑惑的问题,因为理论上只要当前线// 程进入有限/无限等待状态中,则无论是因为信号/中断/超时而被唤醒都意味着其必然会被迁移至同步队列中。// 其中信号唤醒会在AQS独占线程将独占节点迁移至队列后执行,而中断/超时唤醒发生时虽然独占节点依然处于// 条件队列中,但后续也会立即执行,即当前线程必然会在判断独占节点是否位于同步队列之前将之迁移至同步队// 列中,因此从逻辑上来说似乎完全没有判断的必要,更不要说还是循环判断。// ---- 循环判断独占节点是否位于同步队列中的根本目的是为了避免虚假唤醒,即避免当前线程在条件为达成的情// 况下被唤醒,而所谓的条件自然是独占节点位于同步队列中。事实上,正常情况下当前线程因为信号/中断/超时// 的原因被唤醒是不会出现虚拟唤醒的,即正常情况下当前线程被唤醒后独占节点必然已经处于同步队列中,具体// 原因上文已经上述过。而之所以会出现虚拟唤醒的情况是由于外部条件的影响而使得当前线程无法进入有限/无// 限等待状态或被以外唤醒,而这个就与AQS对线程使用的等待/唤醒工具类LockSupport的机制有关。// ---- LockSupport通过park/unpark方法等待/唤醒线程,但与常规等待/唤醒不同的是LockSupport存在许可的概// 念。线程最多可以持有一个许可,当线程持有的许可数量 < 0时线程就会进入有限/无限等待状态,因此// park/unpark方法本质上就是在递减/递增线程的许可。线程的默认许可数为0,因此该状态下当对其执行park方// 法时线程就会因为许可数 < 0而进入有限/无限等待状态,而在当对其执行unpark()方法时就会使得许可数为0而// 唤醒。这种情况属于正常思维下的标准流程,但除此之外还存在一些相对不标准的流程,即如果先对线程执行被// unpark()方法而使得许可数量为1,则在对其执行park()方法时也只能使其为许可数量为0而无法进入有限/无限等// 待状态。而这就是造成虚假唤醒的根本原因。// ---- 虚假唤醒并不是AQS内部对线程执行LockSupport.park/unpark方法导致的,因为上文已经说过信号唤醒只有// 在成功将独占节点迁移至同步队列后才会执行,因此这种情况当前线程如论时具备许可而无法进入有限/无限等待// 状态还是被唤醒都必然保证了独占节点位于同步队列中,因此虚假唤醒的情况实际上是由外部的其它线程对当前// 线程执行LockSupport.unpark()方法造成的。这种LockSupport.unpark()方法的执行不受AQS内部逻辑的控制,因// 此就可能导致线程在独占节点未迁移至同步队列的情况下无法进入有限/无限等待状态或被唤醒。并且由于这种// 方法的次数和时机都无法被预知,因此一次判断是不够的,必须循环判断到达成条件为止。循环判断的存在使得// 外部唤醒无论被执行了多少次都能够保证线程不会在为达成条件的情况下尝试重新能获取状态,即使其可能只是// 在不断的自旋而不是进入有限/无限状态。while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}// ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所// 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状// 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:// 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;// clean up if cancelled// 如果取消则清理// ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独// 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所// 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null// 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样// 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断// 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。if (node.nextWaiter != null)unlinkCancelledWaiters();// ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断。if (interruptMode != 0)reportInterruptAfterWait(interruptMode);}/*** Implements timed condition wait.* 实现定时的条件等待。* <ol>* <li> If current thread is interrupted, throw InterruptedException.* 如果当前线程被中断,抛出中断异常。* <li> Save lock state returned by {@link #getState}.* 保存通过getState()方法返回的锁状态。* <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.* 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。* <li> Block until signalled, interrupted, or timed out.* 阻塞直至收到信号,中断,或超时。* <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.* 通过将保存的锁状态作为桉树调用指定的acquire()方法版本获取状态。* <li> If interrupted while blocked in step 4, throw InterruptedException.* 如果在步骤四阻塞期间被中断,抛出中断异常。* </ol>** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 等待纳秒* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获* 取之前释放的所有状态并返回剩余等待时间。在成功获取状态后,如果存在中断并发的情况下,如果当前线程因为* 信号而唤醒则需要保留中断状态;否则抛出中断异常。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常免,否则将当前线程封装为[等待状态]为* CONDITION(-2:条件)的独占节点尾插至条件队列中。* ---- 随后当前线程会以独占模式释放当前持有的所有[状态],该行为意味着其解除了对AQS的独占,因此从此处开始* 将由线程并发的竞争获取[状态]。* ---- 计算方法的等待截止时间戳,随后进入判断独占节点是否位于同步队列的循环。在循环中,当前线程首先会判断* 等待时间是否超时,是则强制插入至同步队列中并结束循环;否则判断剩余的等待时间是否 >= 自旋阈值。是则进入* 令自身进入进入有限等待状态;否则继续执行循环。因为如果等待时间非常短的话等待就是不值得的,因为Java线* 程状态的转换也是一件相当耗时耗力的行为,还不如直接自旋等待。* ---- 当前线程因为信号/中断/超时等待原因后,会判断自身时因为信号/超时而唤醒还是因为中断而唤醒,已决定在* 有并发参与的情况下当前线程在方法结束时是抛出中断异常还是重新中断线程以保留中断状态。而如果没有被中断* 则重新循环。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占* 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,* 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意* 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不* 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占* 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。* ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,最* 后返回剩余的等待时间戳。*/@Overridepublic final long awaitNanos(long nanosTimeout) throws InterruptedException {// ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常免,否则将当前线程封装为[等待状态]为// CONDITION(-2:条件)的独占节点尾插至条件队列中。if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();// ---- 随后当前线程会以独占模式释放当前持有的所有[状态],该行为意味着其解除了对AQS的独占,因此从此处// 开始将由线程并发的竞争获取[状态]。int savedState = fullyRelease(node);// ---- 计算方法的等待截止时间戳,随后进入判断独占节点是否位于同步队列的循环。在循环中,当前线程首先会// 判断等待时间是否超时,是则强制插入至同步队列中并结束循环;否则判断剩余的等待时间是否 >= 自旋阈值。// 是则进入令自身进入进入有限等待状态;否则继续执行循环。因为如果等待时间非常短的话等待就是不值得的,// 因为Java线程状态的转换也是一件相当耗时耗力的行为,还不如直接自旋等待。// ---- 当前线程因为信号/中断/超时等待原因后,会判断自身时因为信号/超时而唤醒还是因为中断而唤醒,已决// 定在有并发参与的情况下当前线程在方法结束时是抛出中断异常还是重新中断线程以保留中断状态。而如果没有// 被中断则重新循环。final long deadline = System.nanoTime() + nanosTimeout;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (nanosTimeout <= 0L) {transferAfterCancelledWait(node);break;}if (nanosTimeout >= spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;nanosTimeout = deadline - System.nanoTime();}// ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所// 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状// 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:// 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;// ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独// 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所// 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null// 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样// 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断// 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。if (node.nextWaiter != null)unlinkCancelledWaiters();// ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,// 最后返回剩余的等待时间戳。if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return deadline - System.nanoTime();}/*** Implements absolute timed condition wait.* 实现绝对的定时等待。* <ol>* <li> If current thread is interrupted, throw InterruptedException.* 如果当前线程被中断,抛出中断异常。* <li> Save lock state returned by {@link #getState}.* 保存通过getState()方法返回的锁状态。* <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.* 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。* <li> Block until signalled, interrupted, or timed out.* 阻塞直至收到信号,中断,或超时。* <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.* 通过将保存的锁状态作为参数调用指定的acquire()方法版本获取状态。* <li> If interrupted while blocked in step 4, throw InterruptedException.* 如果在步骤四阻塞期间被中断,抛出中断异常。* <li> If timed out while blocked in step 4, return false, else true.* 如果在步骤四等待超时,返回false;否则返回true。* </ol>** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 等待直至* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获* 取之前释放的所有状态并返回是否超时,true表示是;false表示否。在成功获取状态后,如果存在中断并发的情况* 下,如果当前线程因为信号而唤醒则需要保留中断状态;否则抛出中断异常。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等待* 状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。* ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首先* 会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,直* 至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并发的* 情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占* 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,* 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意* 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不* 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占* 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。* ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,* 最后返回剩余的等待时间戳。*/@Overridepublic final boolean awaitUntil(Date deadline) throws InterruptedException {// ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等// 待状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。long abstime = deadline.getTime();if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();// ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首// 先会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,// 直至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并// 发的情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。int savedState = fullyRelease(node);boolean timedout = false;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (System.currentTimeMillis() > abstime) {timedout = transferAfterCancelledWait(node);break;}LockSupport.parkUntil(this, abstime);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}// ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所// 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状// 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:// 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;// ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独// 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所// 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null// 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样// 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断// 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。if (node.nextWaiter != null)unlinkCancelledWaiters();// ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,// 最后返回是否超时。if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return !timedout;}/*** Implements timed condition wait.* 实现定时等待* <ol>* <li> If current thread is interrupted, throw InterruptedException.* 如果当前线程被中断,抛出中断异常。* <li> Save lock state returned by {@link #getState}.* 保存通过getState()方法返回的锁状态。* <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.* 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。* <li> Block until signalled, interrupted, or timed out.* 阻塞直至收到信号,中断,或超时。* <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.* 通过将保存的锁状态作为参数调用指定的acquire()方法版本获取状态。* <li> If interrupted while blocked in step 4, throw InterruptedException.* 如果在步骤四阻塞期间被中断,抛出中断异常。* <li> If timed out while blocked in step 4, return false, else true.* 如果在步骤四等待超时,返回false;否则返回true。* </ol>** @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 等待* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获* 取之前释放的所有状态并返回是否超时,true表示是;false表示否。在成功获取状态后,如果存在中断并发的情况* 下,如果当前线程因为信号而唤醒则需要保留中断状态;否则抛出中断异常。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等待* 状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。* ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首先* 会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,直* 至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并发的* 情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[* 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期* 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),* 意味着在整体流程结束后需要重新线程中断以保持中断状态。* ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占* 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,* 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意* 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不* 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占* 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。* ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,* 最后返回剩余的等待时间戳。*/@Overridepublic final boolean await(long time, TimeUnit unit) throws InterruptedException {// ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等// 待状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。long nanosTimeout = unit.toNanos(time);if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();// ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首// 先会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,// 直至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并// 发的情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。int savedState = fullyRelease(node);final long deadline = System.nanoTime() + nanosTimeout;boolean timedout = false;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (nanosTimeout <= 0L) {timedout = transferAfterCancelledWait(node);break;}if (nanosTimeout >= spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;nanosTimeout = deadline - System.nanoTime();}// ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所// 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状// 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:// 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;// ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独// 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所// 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null// 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样// 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断// 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。if (node.nextWaiter != null)unlinkCancelledWaiters();// ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,// 最后返回是否超时。if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return !timedout;}// support for instrumentation// 为仪表化支持/*** Returns true if this condition was created by the given synchronization object.* 如果当前条件对象通过指定同步对象创建则返回true。** @return {@code true} if owned 如果有用则为true* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 是否被拥有* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 判断当前条件对象是否由指定同步对象创建,是则返回true;否则返回false。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法会将指定同步对象与当前同步对象做对比,相同则返回true;否则返回false。*/final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {return sync == AbstractQueuedSynchronizer.this;}/*** Queries whether any threads are waiting on this condition. Implements* {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.* 查询是否由线程在当前条件中等待。实现AbstractQueuedSynchronizer#hasWaiters(ConditionObject)。** @return {@code true} if there are any waiting threads  如果有任意等待线程则为true。* @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}*                                      非法监视状态异常:如果isHeldExclusively()返回false。* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 是否存在等待者* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 判断当前条件对象中是否存在等待的线程,是则返回true;否则返回false。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。* 随后方法会遍历的条件队列,如果在其中发现了[等待状态]为CONDITION(-2:条件)的节点则返回true;否则在遍* 历结束后返回false。*/protected final boolean hasWaiters() {if (!isHeldExclusively())throw new IllegalMonitorStateException();for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION)return true;}return false;}/*** Returns an estimate of the number of threads waiting on this condition.* Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.* 返回在当前条件中等待的线程的估计值。实现AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)。** @return the estimated number of waiting threads 等待线程的估计值。* @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}*                                      非法监视状态异常:如果isHeldExclusively()返回false。* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 获取等待队列长度* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 获取在当前条件对象中等待的线程的数量估计值。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。* 随后方法会遍历的条件队列,并记录[等待状态]为CONDITION(-2:条件)的独占节点总数并返回。*/protected final int getWaitQueueLength() {if (!isHeldExclusively())throw new IllegalMonitorStateException();int n = 0;for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION)++n;}return n;}/*** Returns a collection containing those threads that may be waiting on this Condition. Implements* {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.** @return the collection of threads 线程集* @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}*                                      非法监视状态异常:如果isHeldExclusively()返回false。* @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------* 获取等待线程集* @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------* 获取在当前条件对象中等待的线程估计集。* @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------* ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。* 随后方法会遍历的条件队列,并保存[等待状态]为CONDITION(-2:条件)的独占节点[线程],最后以集的形式返回。*/protected final Collection<Thread> getWaitingThreads() {if (!isHeldExclusively())throw new IllegalMonitorStateException();ArrayList<Thread> list = new ArrayList<Thread>();for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION) {Thread t = w.thread;if (t != null)list.add(t);}}return list;}}
关键字:广告设计公司税务筹划_青岛手机建站模板_网络营销的目的是_软文写作

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: