AbstractQueuedSynchronizer(AQS)

摘要排队同步器类
它提供了一个框架,用于实现阻塞锁和相关的同步器,如信号量, CountDownLatch等。获取的基本算法是try acquire,若是成功则返回其余排队线程(若是它还没有排队)并阻止当前线程。一样,发布的基本算法是try release,若是成功,则取消阻塞队列中的第一个线程,不然只返回。线程将在先进先出(FIFO)等待队列中等待。抽象方法 tryAcquire()和tryRelease()将根据须要由子类实现。html

以独家模式获取
以独占模式获取的通用算法
AbstractQueuedSynchronizer(AQS)java

在上面的图中'shouldParkAfterFailedAcquire?' 验证前任的等待状态是否为SIGNAL。若是是,它肯定前任线程将在其释放时SIGNAL,所以它将当即阻止,不然它可能会重试获取锁,以防它是队列中的第一个节点。
AbstractQueuedSynchronizer(AQS)算法

队列
若是线程没法获取锁,它将被放入队列中。若是队列尚不存在,它将使用虚拟标头初始化它,而后将其自身连接到它。头部的“下一个”和节点的“上一个”将被连接。新节点也成了尾巴。标题节点的等待状态将设置为SIGNAL,以便当全部者线程释放锁时,它能够通知头节点的后继者获取锁。线程将再次尝试获取锁定以确保它在实际停放以前没法获取。安全

AbstractQueuedSynchronizer(AQS)框架

所以,只要其前任节点的等待状态被设置为SIGNAL,就能够安全地停放未能得到锁的线程,所以一旦前一个被释放,它就能够重试获取锁。
若是前一个被取消,它将跳过全部被取消的前任,以重置其等待线程的next和prev指针。ui

AbstractQueuedSynchronizer(AQS)
发布
AbstractQueuedSynchronizer(AQS)线程

子类将根据他们的要求实现“try Release”。一旦发布,标头节点的后继节点须要发信号,以便它能够从新尝试获取。若是没有头,则表示队列中没有线程,所以没有人发出信号。若是磁头存在,则确保等待状态不为零。若是它为零,则意味着不须要发信号通知后继节点。指针

Unpark后继节点的线程
线程到unpark是在后继节点,一般只是下一个节点。
状况1:若是头部的等待状态<0,则清除等待状态。若是后继节点(P1)未处于取消状态,则取消后继节点的线程,以便它能够重试获取。
AbstractQueuedSynchronizer(AQS)htm

状况2:若是后继节点取消或为null,则从尾部向后遍历以查找实际未取消的后继节点。
AbstractQueuedSynchronizer(AQS)队列

一旦取消停放线程,其节点就成了新头。老头将脱钩。若是未能得到,将从新停放。头节点的等待状态设置为0将重置为SIGNAL。

发布共享
这与独家发布相似。它还确保释放传播。

以共享模式获取
这相似于独家收购。它还将释放传播到队列中等待获取共享锁的其余等待线程。一旦锁定被释放,它就会取消其后继节点的停放,后者又将释放传播到下一个节点。

取消
在尝试获取时可能存在运行时异常,在这种状况下将取消上下文中的节点。若是节点被取消,咱们必须确保其后继节点正确连接到有效的前任节点,所以可能必须调整连接。若是其前任节点已经处于取消状态,则将跳过这些节点以到达具备等待状态<= 0的适当的前任节点。
若是要取消的节点自己是尾节点,则将简单地将其移除。它的前身节点将成为新的尾巴。新尾部的“下一个”连接将指向null。
若是等待状态<0,则表示后继者须要信号,尝试设置前任的下一个连接,以便得到一个。若是前任是头节点自己,则它将唤醒其后继节点。

状况1:要取消的节点是尾节点
AbstractQueuedSynchronizer(AQS)

状况2:取消节点的前任是head,如今将发信号通知被取消节点的下一个节点被唤醒。
原文地址:https://www.javarticles.com/2...

相关文章
相关标签/搜索