深入理解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.同步等待队列【主要用于维护获取锁失败时入队的线程】【深入理解AQS--jdk层面管程实现【管程详解的补充】】【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为没有加锁

经验总结扩展阅读