一、什么是AQS
1.1 概念
AbstractQueuedSynchronizer抽象同步队列,其定义了一套多线程访问共享资源的同步器框架,通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态。
1.2 基石
很多同步类实现都依赖于AQS,如常用的ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock等等。
二、作用
用于管理加锁导致的阻塞。当多个线程争用资源时,未抢到资源的线程则会进入此队列,在其内部进行管理。
如果共享资源被别的线程占用时,就需要一定的阻塞等待唤醒机制来保证锁的分配。这个机制主要是CLH队列(FIFO先进先出)的变体来实现,将暂时获取不到锁的线程加入队列中,这个队列就是AQS的抽象表现。它将请求共享资源的线程封装成队列的节点(Node),通过CAS、自旋、LockSupport.park()的方式,来维护队列的同步状态state(volatile int类型),使并发达到同步控制的效果。
三、AQS内部体系架构
3.1 AQS自身
AQS的int变量state:表示锁的占用状态。
AQS的CLH队列:Node队列。(Craig、Landin and Hagersten 队列,是个单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO))
3.2 内部类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; static final int CONDITION = -2; static final int PROPAGATE = -3; /** * CANCELLED,值为1,表示当前的线程被取消 * SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark; * CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中; * PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行; * 值为0,表示当前节点在sync队列中,等待着获取锁。 */ volatile int waitStatus; // 前驱结点 volatile Node prev; // 后继结点 volatile Node next; // 与该结点绑定的线程 volatile Thread thread; // 存储condition队列中的后继节点 Node nextWaiter; // 是否为共享模式 final boolean isShared() { return nextWaiter == SHARED; } // 获取前驱结点 final Node predecessor() throwsNullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial heador SHARED marker } Node(Thread thread, Node mode) { // Used byaddWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { //Used by Condition this.waitStatus = waitStatus; this.thread = thread; } }