一:什么是AQS
AbstractQueuedSychronizer
整个JUC体系的基石,主要用于解决锁分配给“谁”的问题:
- FIFO,CLH变体的虚拟双向对象
- state:依靠单个原子int值来表示状态,通过占用和释放方法改变状态值
如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态(waitState)封装成队列的结点对象(Node) ,通过CAS、自旋以及LockSupport.park()的方式,维护state变 量的状态,使并发达到同步的效果。
二:AQS有关的锁
都是通过Sync实现AQS
相关关系图:NofairSync、FairSync(重点)
三:相关组成
3.1 AbstractQueuedSychronizer组成
AQS使用一个volatile的int类型的state来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作将每条要去抢占资源的线程封装成一个Node节点来实现锁的分配,通过CAS完成对State值的修改。
3.2 Node组成
四:ReentrantLock原理为例
4.1 原理架构图
4.2 构造方法
可以实现非公平锁和公平锁
公平锁: 公平锁讲究先来先到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入等待队列中;
非公平锁:不管是否有等待队列,如果可以获取锁,则立刻占有锁对象。也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还是需要参加竞争锁(存在线程竞争的情况下),后来的线程(队外的锁)可能不讲武德插队夺锁了。
4.3 lock方法
**非公平锁:lock方法 **
①第一个线程进来,此时无线程争抢,获取锁成功将state由0改为1
②第二个线程进来,此时cas发现状态位不为0,进入acquire尝试抢占
公平锁:lock方法
4.4 acquire方法
抢锁失败进入队列,
4.5 tryAcquire方法
模板方法交给子类实现
hasQueuedPredecessors.是公平锁加锁时判断等待队列中是否存在有效节点的方法
非公平锁:tryAcquire具体实现
4.6 addWaiter详解
入队操作三步:pre指向之前的尾节点,将此节点设置为尾节点,之前的尾节点的next指向当前节点。
4.7 acquireQueued方法
4.8 unlock方法