AbstractQueuedSynchronizer
相关类图如:AQS类图所示
AbstractQueuedSynchronizer是用来实现锁或者其他同步器组件的公共基础部分的抽象实现。是重量级基础框架及整个JUC体系的基石,主要用于解决锁分配给谁的问题。整体就是一个抽象的FIFO队列来完成资源获取线程的排队工作,并通过int变量表示持有锁的状态
CLH队列,全程Craig、Landin and Hagersten队列,是一个单向链表,AQS中的队列是CLH的一种变体的虚拟双向FIFO队列。逻辑示意图如图:虚拟FIFO双向队列示意图所示
大部分我们使用并发组件基本上都和AQS有关,例如CountDownLatch,ReentranLock之类得
锁和同步器的关系
锁:面向锁的使用者,定义了程序员和锁交互的使用层API,隐藏了实现细节,调用即可
同步器:面向锁的实现者,统一规范并简化了锁的实现,将其抽象出来,屏蔽了同步状态管理同步队列的管理和维护,阻塞线程排队和通知、唤醒机制等,是一切锁和同步组件实现的——公共基础部分
AQS内部静态类Node的相关介绍
static final class Node {
//共享锁方式
static final Node SHARED = new Node();
//独占锁方式
static final Node EXCLUSIVE = null;
//线程被取消
static final int CANCELLED = 1;
//后继线程需要唤醒
static final int SIGNAL = -1;
//等待condition唤醒
static final int CONDITION = -2;
//共享式同步状态获取将会无条件传播下去
static final int PROPAGATE = -3;
//初始化状态0,状态值是上面的几种
volatile int waitStatus;
//前驱节点
volatile Node prev;
//后继节点
volatile Node next;
//封装到Node中的线程
volatile Thread thread;
}
等待状态相关属性说明如下
waitStatus | 含义 |
---|---|
0 | 当一个Node节点初始化时的状态的默认值 |
CANCELLED:1 | 表示线程获取锁的请求已经取消 |
CONDITION:-2 | 表示节点在等待队列中,节点线程等待唤醒 |
PROPAGATE:-3 | 当前线程处于SHARED情况下,该字段才会使用 |
SIGNAL:-1 | 表示线程已经准备好了,就等资源释放 |
等待锁方式状态说明如下
模式 | 含义 |
---|---|
SHARED | 表示线程以共享的模式等待锁 |
EXCLUSIVE | 表示线程以独占的模式等待锁 |
AQS源码分析
以ReentrantLock中的非公平锁为例,相关类图如:ReentrantLock相关类图所示
![image-20221207214309169](https://img-blog.csdnimg.cn/img_convert/97e68b99711644f2b321b261e9ad74bf.png)
ReentrantLock非公平锁加锁源码解读
private final ReentrantLock lock=new ReentrantLock();
//实例化一个非公平锁,将其引用赋值给ReentrantLock的内部类Sync类型的sync成员变量
public ReentrantLock() {
sync = new NonfairSync();
}
//执行加锁操作
lock.lock();
public void lock() {
/**调用成员变量的acquire方法,
因为内部类继承了AbstractQueuedSynchronizer类并且没有重写acquire方法所以实际上还是调的父类的方法**/
sync.acquire(1);
}
//AQS中的acquire方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
现在单独来解析AQS方法中加锁调用的三个方法 tryAcquire,acquireQueued,addWaiter
tryAcquire方法
该方法位于AQS中,是一个钩子方法,我们直到AQS实际上是使用的模板方法设计模式,所以通常会留下钩子方法以供子类去实现
//调用了AQS中的tryAcquire,这是一个钩子方法,留给子类去实现的,具体的操作结果应该是由子类来做的 protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }
通过架构图可以知道,ReentrantLock的静态内部类Sync继承了AQS,而非公平锁的加锁又是由ReentrantLock的静态内部类NonfairSync来实现的,该类又是继承的ReentrantLock静态内部类Sync的,所以,本质上来说,实现AQS的tryAcquire方法是由ReentrantLock的静态内部类NonfairSync实现的。该方法主要就是进行抢锁操作,判断如果AQS中的锁状态标志位位0则,表示没有线程占用锁CAS操作设置锁的状态位为1,并且以独占的方式获取到锁。如果锁状态标志位不为0,那么就判断,获取到锁的线程是不是自己,如果是则CAS操作将AQS中的锁状态标记位加1表示当前线程获取到锁的次数。否则的话就是抢占失败返回false
/** ReentrantLock类中的静态内部类NonfairSync, 继承了ReentrantLock的静态内部类Sync, Sync又是继承的AQS, 所以AQS中的钩子方法就是由孙子类NonfairSync来进行实现了 **/ protected final boolean tryAcquire