1.5w字,30图带你彻底掌握 AQS!(建议收藏)( 七 )
private final boolean parkAndCheckInterrupt() {// 阻塞线程LockSupport.park(this);// 返回线程是否中断过 , 并且清除中断状态(在获得锁后会补一次中断)return Thread.interrupted();}
这里的阻塞线程很容易理解 , 但为啥要判断线程是否中断过呢 , 因为如果线程在阻塞期间收到了中断 , 唤醒(转为运行态)获取锁后(acquireQueued 为 true)需要补一个中断 , 如下所示:
public final void acquire(int arg) {if (!tryAcquire(arg) }
至此 , 获取锁的流程已经分析完毕 , 不过还有一个疑惑我们还没解开:前文不是说 Node 状态为取消状态会被取消吗 , 那 Node 什么时候会被设置为取消状态呢 。
回头看 acquireQueued
final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {// 省略自旋获取锁代码} finally {if (failed)// 如果线程自旋中因为异常等原因获取锁最终失败 , 则调用此方法cancelAcquire(node);}}
看最后一个 cancelAcquire 方法 , 如果线程自旋中因为异常等原因获取锁最终失败 , 则会调用此方法
private void cancelAcquire(Node node) {// 如果节点为空 , 直接返回if (node == null)return;// 由于线程要被取消了 , 所以将 thread 线程清掉node.thread = null;// 下面这步表示将 node 的 pre 指向之前第一个非取消状态的结点(即跳过所有取消状态的结点),waitStatus > 0 表示当前结点状态为取消状态Node pred = node.prev;while (pred.waitStatus > 0)node.prev = pred = pred.prev;// 获取经过过滤后的 pre 的 next 结点 , 这一步主要用在后面的 CAS 设置 pre 的 next 节点上Node predNext = pred.next;// 将当前结点设置为取消状态node.waitStatus = Node.CANCELLED;// 如果当前取消结点为尾结点 , 使用 CAS 则将尾结点设置为其前驱节点 , 如果设置成功 , 则尾结点的 next 指针设置为空if (node == tail} else {// 这一步看得有点绕 , 我们想想 , 如果当前节点取消了 , 那是不是要把当前节点的前驱节点指向当前节点的后继节点 , 但是我们之前也说了 , 要唤醒或阻塞结点 , 须在其前驱节点的状态为 SIGNAL 的条件才能操作 , 所以在设置 pre 的 next 节点时要保证 pre 结点的状态为 SIGNAL , 想通了这一点相信你不难理解以下代码 。int ws;if (pred != headif (next != null} else {// 如果 pre 为 head , 或者pre 的状态设置 SIGNAL 失败 , 则直接唤醒后继结点去竞争锁 , 之前我们说过 ,SIGNAL 的结点取消(或释放锁)后可以唤醒后继结点unparkSuccessor(node);}node.next = node; // help GC}}
这一段代码有点绕 , 我们一个个来看 , 首先考虑以下情况
1、首先第一步当前节点之前有取消结点时 , 则逻辑如下
文章插图
2、如果当前结点既非头结点的后继结点 , 也非尾结点 , 即步骤 1 所示 , 则最终结果如下
文章插图
这里肯定有人问 , 这种情况下当前节点与它的前驱结点无法被 GC 啊 , 还记得我们上文分析锁自旋时的处理吗,再看下以下代码
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {int ws = pred.waitStatus;// 省略无关代码if (ws > 0) {// 移除取消状态的结点do {node.prev = pred = pred.prev;} while (pred.waitStatus > 0);pred.next = node;}return false;}
这段代码会将 node 的 pre 指向之前 waitStatus 为非 CANCEL 的节点
推荐阅读
- 曾被京东物流效仿,让雷军花1亿拯救,如今欠7000万彻底出局
- 线下市场彻底“乱了”!小米宣布新规!华为捆绑加价行为迎争议
- 一波未平一波又起,我买个菜就欠了一笔贷款?美团这次彻底没话说
- 微软|外媒:微软将对Windows 10界面进行彻底改进 已招兵买马
- 华为P50真机图曝光:外形变化很彻底
- 京东7FRESH迎来彻底变革
- Windows 10等软件全部封杀 Flash彻底说再见
- 尼康相机将于2021年底前彻底告别“日本产”
- 微信的一项更新,彻底让用户“反感”,这是要开启直播时代?
- 华为迎来最大希望!国内将成立“芯片大学”,彻底解决卡脖子问题