AQS双向链表

双向链表的每个数据节点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点(head)和后继结点(tail)。

AQS实际上通过头尾指针来管理同步队列,同时实现包括获取锁失败的线程进行入队,释放锁时对同步队列中的线程进行通知等核心方法。

一、添加节点

  1. 如果队列为空,会初始化队列。
    第一个加进来的新节点既是头也是尾,前后都没有节点。


    初始化队列
  1. 新增一个节点
    添加节点会涉及到三个变化:
  • 新的线程封装成Node节点追加到同步队列中,设置prev节点以及修改当前节点的前置节点的next节点指向自己
  • 通过CAS讲tail重新指向新的尾部节点
    -头节点会更新waitStatus为-1


    新增一个节点-线程t1
新增节点-线程t2

二、移除节点

我们以下图来介绍下等待队列时如何移除节点的。如图中所示队列中有t1,t2两个线程。假设此时持有锁的线程t0释放锁unlock。那么队列中线程移除步骤如下:

  • 线程先释放state资源
  • 通过 unparkSuccessor 唤醒head的后继节点,因为后继节点有可能进入了waitting状态,将waitStatus值设为0.
  • 判断node的后继节点next是否有效,如果无效,则从队列的tail节点开始往前遍历,直到找到第一个有效的节点
  • 唤醒线程后,在acquireQueued自旋获取锁,头节点移除队列,获取锁的节点设置为头。
移除节点前状态
移除节点

你可能感兴趣的:(AQS双向链表)