一.简介
AbstractQueuedSynchronizer 中文翻译叫做同步器,简称 AQS,是各种各样锁的基础,比如说 ReentrantLock 等等,这些我们经常用的锁底层实现都是 AQS。
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
1.AQS 是个抽象类,就是给各种锁子类继承用的,AQS 定义了很多如何获得锁,如何释放锁的抽象方法,目的就是为了让子类去实现;
2.继承了 AbstractOwnableSynchronizer,AbstractOwnableSynchronizer 的作用就是为了知道当前是那个线程获得了锁,方便监控用的
二.基本属性
AQS 的属性可简单分为四类:同步器简单属性、同步队列属性、条件队列属性、公用 Node。
2.1简单属性
最重要的就是 state 属性,是 int 属性的,所有继承 AQS 的锁都是通过这个字段来判断能不能获得锁,能不能释放锁。
2.2同步队列属性
首先我们介绍以下同步队列:当多个线程都来请求锁时,某一时刻有且只有一个线程能够获得锁(排它锁),那么剩余获取不到锁的线程,都会到同步队列中去排队并阻塞自己,当有线程主动释放锁时,就会从同步队列头开始释放一个排队的线程,让线程重新去竞争锁。
总结:所以同步队列的主要作用阻塞获取不到锁的线程,并在适当时机释放这些线程。
2.3条件队列属性
首先我们介绍下条件队列:条件队列和同步队列的功能一样,管理获取不到锁的线程,底层数据结构也是链表队列,但条件队列不直接和锁打交道,但常常和锁配合使用,是一定的场景下,对锁功能的一种补充。
ConditionObject 我们就称为条件队列,我们需要使用时,直接 new ConditionObject () 即可。
2.4共有Node
Node 非常重要,即是同步队列的节点,又是条件队列的节点,在入队的时候,我们用 Node 把线程包装一下,然后把 Node 放入两个队列中
其中比较重要的是waitStatus 字段
// 表示当前节点的状态,通过节点的状态来控制节点的行为
// 普通同步节点,就是 0 ,条件节点是 CONDITION -2
volatile int waitStatus;
三.获取锁
获取锁最直观的感受就是使用 Lock.lock () 方法来获得锁,最终目的是想让线程获得对资源的访问权。
Lock 一般是 AQS 的子类,lock 方法根据情况一般会选择调用 AQS 的 acquire 或 tryAcquire 方法。
acquire 方法 AQS 已经实现了,tryAcquire 方法是等待子类去实现,acquire 方法制定了获取锁的框架,先尝试使用 tryAcquire 方法获取锁,获取不到时,再入同步队列中等待锁。tryAcquire 方法 AQS 中直接抛出一个异常,表明需要子类去实现,子类可以根据同步器的 state 状态来决定是否能够获得锁。
3.1排他锁:
// 排它模式下,尝试获得锁
public final void acquire(int arg) {
// tryAcquire 方法是需要实现类去实现的,实现思路一般都是 cas 给 state 赋值来决定是否能获得锁
if (!tryAcquire