摘要:线程将再次尝试获取锁定以确保它在实际停放之前无法获取。如果没有头,则表示队列中没有线程,因此没有人发出信号。如果后继节点未处于取消状态,则取消后继节点的线程,以便它可以重试获取。
摘要排队同步器类
它提供了一个框架,用于实现阻塞锁和相关的同步器,如信号量, CountDownLatch等。获取的基本算法是try acquire,如果成功则返回其他排队线程(如果它尚未排队)并阻止当前线程。同样,发布的基本算法是try release,如果成功,则取消阻塞队列中的第一个线程,否则只返回。线程将在先进先出(FIFO)等待队列中等待。抽象方法 tryAcquire()和tryRelease()将根据需要由子类实现。
以独家模式获取
以独占模式获取的通用算法
AbstractQueuedSynchronizer(AQS)
在上面的图中"shouldParkAfterFailedAcquire?" 验证前任的等待状态是否为SIGNAL。如果是,它确定前任线程将在其释放时SIGNAL,因此它将立即阻止,否则它可能会重试获取锁,以防它是队列中的第一个节点。
AbstractQueuedSynchronizer(AQS)
队列
如果线程无法获取锁,它将被放入队列中。如果队列尚不存在,它将使用虚拟标头初始化它,然后将其自身链接到它。头部的“下一个”和节点的“上一个”将被链接。新节点也成了尾巴。标题节点的等待状态将设置为SIGNAL,以便当所有者线程释放锁时,它可以通知头节点的后继者获取锁。线程将再次尝试获取锁定以确保它在实际停放之前无法获取。
AbstractQueuedSynchronizer(AQS)
因此,只要其前任节点的等待状态被设置为SIGNAL,就可以安全地停放未能获得锁的线程,因此一旦前一个被释放,它就可以重试获取锁。
如果前一个被取消,它将跳过所有被取消的前任,以重置其等待线程的next和prev指针。
AbstractQueuedSynchronizer(AQS)
发布
AbstractQueuedSynchronizer(AQS)
子类将根据他们的要求实现“try Release”。一旦发布,标头节点的后继节点需要发信号,以便它可以重新尝试获取。如果没有头,则表示队列中没有线程,因此没有人发出信号。如果磁头存在,则确保等待状态不为零。如果它为零,则意味着不需要发信号通知后继节点。
Unpark后继节点的线程
线程到unpark是在后继节点,通常只是下一个节点。
情况1:如果头部的等待状态<0,则清除等待状态。如果后继节点(P1)未处于取消状态,则取消后继节点的线程,以便它可以重试获取。
AbstractQueuedSynchronizer(AQS)
情况2:如果后继节点取消或为null,则从尾部向后遍历以查找实际未取消的后继节点。
AbstractQueuedSynchronizer(AQS)
一旦取消停放线程,其节点就成了新头。老头将脱钩。如果未能获得,将重新停放。头节点的等待状态设置为0将重置为SIGNAL。
发布共享
这与独家发布类似。它还确保释放传播。
以共享模式获取
这类似于独家收购。它还将释放传播到队列中等待获取共享锁的其他等待线程。一旦锁定被释放,它就会取消其后继节点的停放,后者又将释放传播到下一个节点。
取消
在尝试获取时可能存在运行时异常,在这种情况下将取消上下文中的节点。如果节点被取消,我们必须确保其后继节点正确链接到有效的前任节点,因此可能必须调整链接。如果其前任节点已经处于取消状态,则将跳过这些节点以到达具有等待状态<= 0的适当的前任节点。
如果要取消的节点本身是尾节点,则将简单地将其移除。它的前身节点将成为新的尾巴。新尾部的“下一个”链接将指向null。
如果等待状态<0,则表示后继者需要信号,尝试设置前任的下一个链接,以便获得一个。如果前任是头节点本身,则它将唤醒其后继节点。
情况1:要取消的节点是尾节点
AbstractQueuedSynchronizer(AQS)
情况2:取消节点的前任是head,现在将发信号通知被取消节点的下一个节点被唤醒。
原文地址:https://www.javarticles.com/2...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/75352.html
摘要:线程将再次尝试获取锁定以确保它在实际停放之前无法获取。如果没有头,则表示队列中没有线程,因此没有人发出信号。如果后继节点未处于取消状态,则取消后继节点的线程,以便它可以重试获取。 摘要排队同步器类它提供了一个框架,用于实现阻塞锁和相关的同步器,如信号量, CountDownLatch等。获取的基本算法是try acquire,如果成功则返回其他排队线程(如果它尚未排队)并阻止当前线...
摘要:总结总的来说,操作顺序是进入队列唤醒,成功获得锁将状态变为并将其从转到使再次获得锁执行余下代码。当然这是理由状态下,为了讨论及的原理,实际的操作时序也有可能变化。 AQS Condition 最近面试被问到java concurrent包下有哪些熟悉的,用过的工具。因此来回顾一下,这些工具的底层实现,AbstractQueuedSynchronizer。在网上看到了其他人的一些技术博客...
摘要:总结总的来说,操作顺序是进入队列唤醒,成功获得锁将状态变为并将其从转到使再次获得锁执行余下代码。当然这是理由状态下,为了讨论及的原理,实际的操作时序也有可能变化。 AQS Condition 最近面试被问到java concurrent包下有哪些熟悉的,用过的工具。因此来回顾一下,这些工具的底层实现,AbstractQueuedSynchronizer。在网上看到了其他人的一些技术博客...
摘要:如果此时,锁被释放,需要通知等待线程再次尝试获取锁,公平锁会让最先进入队列的线程获得锁。等待队列节点的操作由于进入阻塞状态的操作会降低执行效率,所以,会尽力避免试图获取独占性变量的线程进入阻塞状态。 今天我们来研究学习一下AbstractQueuedSynchronizer类的相关原理,java.util.concurrent包中很多类都依赖于这个类所提供队列式同步器,比如说常用的R...
阅读 1831·2021-09-24 09:48
阅读 3194·2021-08-26 14:14
阅读 1660·2021-08-20 09:36
阅读 1440·2019-08-30 15:55
阅读 3608·2019-08-26 17:15
阅读 1407·2019-08-26 12:09
阅读 588·2019-08-26 11:59
阅读 3307·2019-08-26 11:57