ConditionObject的await方法分析

136 阅读2分钟

ConditionObject的await方法分析

  • 判断当前线程是否中断,中断直接抛出非法监视器状态异常
  • 要是没有中断则通过addConditionWaiter()方法将该节点加入到Condition的单向链表中
  • 通过fullyRelease(node)方法一次新释放掉锁资源
  • 初始化一个状态模式为0的标记
  • 执行while判断,要是线程不在AQS队列中就挂起该线程(要是在AQS队列中可能有一种情况那就是该线程刚释放锁资源,立刻就被唤醒,所以他会进入AQS队列自然不用去挂起他)
  • 检查当前线程在获取锁资源的时候有没有被中断过

在这里插入图片描述

线程添加到Condition单项链表中的代码分析

  • 获取尾节点
  • 尾节点不为空,并且尾节点的状态值不为-2,那么就取消当前节点,并重新获取尾节点
  • 创建新的节点,并将节点的状态值设置为-2.
  • 如果当前节点是尾节点是null,直接将刚才创建的节点放置为第一个等待节点
  • 否则就排在尾节点的后面
  • 最后返回当前节点

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

分析后半部分await()代码的含义

  • 判断当前线程的中断模式

在这里插入图片描述

  • 解释三目运算符,要是线程没有被中断,返回0
  • THROW_IE:中断唤醒
  • REINTERRUPT:signal唤醒,并且线程在AQS队列中
  • 此处存在一个细节就是Thread.interrupted()能查看当前线程状态并重置当前线程状态

在这里插入图片描述

  • 下面这个方法要是返回true,则意味着线程时中断唤醒并且在AQS队列中,只有以上两个条件都满足才会返回true。
  • 下面这个方法在singal也有一个一样的基于CAS的判断,要是能进来那么就说明是中断唤醒的线程
  • 将当前节点添加到AQS队列
  • 往后判断当前线程是否在AQS队列中,因为基于singal唤醒的线程可能不在AQS队列。

在这里插入图片描述 在这里插入图片描述

isOnSyncQueue(node)分析

  • 判断当前node节点是否在AQS队列上
  • 两个条件当前节点的状态为-2或者当前节点的前一个节点为空都是不在
  • 要是节点的下一个节点不为空就在了,因为在Condition的单向链表中没有next这个指针

在这里插入图片描述

findNodeFromTail(node)队列中找到当前节点

在这里插入图片描述 在这里插入图片描述