深入理解AQS--jdk层面管程实现【管程详解的补充】

什么是AQS1.java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器 。
2.JDK中提供的大多数的同步器如Lock, Latch, Barrier等,都是基于AQS框架来实现的
【1】一般是通过一个内部类Sync继承 AQS
【2】将同步器所有调用都映射到Sync对应的方法
AQS具备的特性:1.阻塞等待队列 , 2.共享/独占  , 3.公平/非公平   ,  4.可重入 , 5.允许中断
AQS定义两种资源共享方式1.Exclusive-独占,只有一个线程能执行 , 如ReentrantLock(详情可查看 深入理解ReentrantLock类锁)
2.Share-共享 , 多个线程可以同时执行 , 如Semaphore/CountDownLatch
AQS定义两种队列1.同步等待队列【主要用于维护获取锁失败时入队的线程】【1】AQS当中的同步等待队列也称CLH队列,CLH队列是Craig、Landin、Hagersten三人发明的一种基于双向链表数据结构的队列,是FIFO先进先出线程等待队列,Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制 。
【2】AQS 依赖CLH同步队列来完成同步状态的管理:
1)当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程
2)当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态 。
3)通过signal或signalAll将条件队列中的节点转移到同步队列 。(由条件队列转化为同步队列)
【3】图示:

深入理解AQS--jdk层面管程实现【管程详解的补充】

文章插图
2.条件等待队列【调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获得锁】【1】AQS中条件队列是使用单向列表保存的,用nextWaiter来连接:
1)调用await方法阻塞线程;
2)当前线程存在于同步队列的头结点,调用await方法进行阻塞(从同步队列转化到条件队列)
3.AQS 定义了5个队列中节点状态:1)值为0,初始化状态,表示当前节点在sync队列中,等待着获取锁 。
2)CANCELLED,值为1 , 表示当前的线程被取消;
3)SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;
4)CONDITION , 值为-2,表示当前节点在等待condition,也就是在condition队列中;
5)PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行;
源码详解(将源码拆分为三块,抽象同步器AbstractQueuedSynchronizer类,节点Node类,条件对象ConditionObject类)AbstractQueuedSynchronizer类解析1.属性值解析
//用链表来表示队列private transient volatile Node head;private transient volatile Node tail;private volatile int state;//可以表示锁的加锁状态【独占锁只为1 , 共享锁可以大于1】,又可以表示锁的重入次数,0为没有加锁2.方法解析
//定义了主体的大体逻辑,如入队,如尝试加锁private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode);// Try the fast path of enq; backup to full enq on failureNode pred = tail;if (pred != null) {node.prev = pred;if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}enq(node);return node;}protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support thisreturn unsafe.compareAndSwapInt(this, stateOffset, expect, update);}//模板方法的处理,如果子类没有实现 , 则子类中调用的话会报错//提供给子类去实现的公平与非公平的逻辑protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();}//释放锁的逻辑protected boolean tryRelease(int arg) {throw new UnsupportedOperationException();}Node类详解1.代码展示
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;//值为0,初始化状态,表示当前节点在sync队列中,等待着获取锁 。//CANCELLED,值为1,表示当前的线程被取消;//SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;//CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中;//PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行;volatile int waitStatus;volatile Node prev;//前驱结点volatile Node next;//后继结点volatile Thread thread; //与节点绑定的线程Node nextWaiter; // 存储condition队列中的后继节点final boolean isShared() {return nextWaiter == SHARED;}final Node predecessor() throws NullPointerException {Node p = prev;if (p == null)throw new NullPointerException();elsereturn p;}Node() {}Node(Thread thread, Node mode) {// Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}Node(Thread thread, int waitStatus) { // Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}}

推荐阅读