AQS - 图1

AQS源码

参考:

AQS的CLH队列
image.png

AQS有一个volatile修饰的int类型状态码,分为三种状态:0没有任务,1被占用,大于1可重入锁。
有一个Node节点构成的双向链表,用于储存等待共享资源的线程。
还有一个Conditional链表,用于

ReentrantLock加锁的过程:

  1. 首先调用lock方法,如果是非公平锁则会先CAS尝试获取锁,成功的话就插队执行。失败了就acquire(1),入队等待。公平锁就直接入队等待。
  2. acquire(1)-》先tryAcquire(1)【尝试获取锁】,失败的话就调用addWaiter入队,采用尾插法。【每添加一个节点,就会将CANCELLED=1的节点删除】
  3. 之后就是队伍内的处理。如果前一个节点不是头节点,就会把前一个节点的状态(waitStatus)置为-1,如果前一个节点已经是-1状态了,就会调用LockSupport阻塞当前节点的线程。
  4. 直到占有AQSstatus的线程结束,唤醒了第二个节点,然后第二个节点的线程获取到锁状态 。将第二个节点置为头节点(thread=null, waitStatus=0),原本的头节点会被GC。

lockInterruptibly()
在节点入队列的过程和获取锁的过程是不响应中断的,其他时候都会做中断判断,有的话抛出中断异常。

条件队列

  • 条件队列建立在某个具体的锁上,只有先获取锁才能使用条件队列
  • 条件队列的唤醒,就是把节点从条件队列移到同步队列,使得节点有机会获取锁。