AQS起到了一个抽象, 封装的作用, 将一些排队, 入队, 加锁, 中断等方法提供出来, 便于其他相关juc锁的使用, 具体的加锁时机和入队时机需要实现类自己控制.
AQS通过维护一个共享状态(state)和一个FIFO的双向链表来管理线程对共享资源的访问.
state用volatile修饰, 表示当前资源的状态. 例如在独占锁中, state为0表示未占用, 为1表示已占用.
当线程尝试获取资源失败时, 会被加入到AQS的等待队列中. 这个队列是一个变体的CLH队列, 采用双向链表结构, 节点包含线程的引用, 等待状态, 以及前后节点的指针.
AQS常见的实现类有ReentrantLock, CountDownLatch等.
ReentrantLock
ReentrantLock是一个基于AQS实现的可重入锁, 支持公平和非公平两种方式.
内部实现依靠一个state变量和两个等待队列: 同步队列和等待队列.
利用CAS修改state来竞争锁.
竞争失败则进入同步队列(双向链表).
条件condation不满足时进入等待队列(单项链表).
是否是公平锁的区别在于: 线程获取锁时是加入到同步队列尾部还是直接利用CAS竞争锁.

扩展
CAS
CAS是一种硬件级别的原子操作, 它比较内存中的某个值是否为预期值, 如果是则更新, 否则不修改.
原理
比较: CAS会检查内存中的某个值是否与预期值相等.
交换: 如果相等, 则修改为新值.
失败重试: 如果不相等, 说明有其他线程修改了这个值, CAS操作失败, 一般会利用重试, 直到成功.
优点
无锁并发: 不会导致线程阻塞, 提高并发性能.
原子性: CAS操作是原子的, 线程安全.
缺点
ABA问题: CAS操作中, 一个值从A变为B再变为A, CAS无法检测到这种变化, 可能导致错误. 可通过JDK的Atomic解决.
自旋开销: CAS操作通过自旋实现, 可能导致CPU资源浪费.
单变量限制: 不实用涉及多个变量的复杂操作.
自旋锁
自旋锁是一种轻量级的锁机制, 线程在获取锁失败后不会立即进入阻塞状态, 而是在循环中反复尝试获取锁, 直至成功.
这种方式避免了线程的上下文切换开销, 所以成为轻量级锁, 适合等待时间较短的场景.
缺点
并发情况下, 可能存在某个线程一直CAS失败, 获取不到锁.
多核CPU在对同一变量进行并发CAS时, 会导致总线风暴.
CLH
针对自旋锁的问题, 演进出的一种基于队列的自旋锁, 它适用于多核CPU环境下的并发场景.
原理
通过维护一个隐式队列, 使线程在等待锁时自旋在本地变量上, 减少对共享变量的竞争.
它将竞争的线程组成一个队列, 通过排队的方式按序争抢锁.
且每个线程不再CAS竞争一个变量, 而是自旋判断排序在自己前面的线程的状态, 如果前面的线程释放锁, 那么后续的线程则竞争锁.

缺点
占用CPU资源: 自旋期间一直占用CPU资源, 适合等待时间较短的场景.