AQS内部结构
AQS就是java中的AbstractQueuedSynchronizer类,属于JUC包下的基类,JUC包下的很多类都继承了AQS。例如:ReentrantLock、ThreadPoolExecutor等
常见的属性变量
state
private volatile int state;
state:由volatile修饰的,int类型的属性变量
通过CAS方式对state变量值进行修改,保证原子性
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;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
node:内部类,是双向链表的节点类型,而且node中存储了一个线程
node中的属性变量:
- SHARED:表示共享锁
- EXCLUSIVE:表示排他锁
- CANCELLED、SIGNAL、CONDITION、PROPAGATE表示线程状态,即waitStatus的取值
AQS的对象抽象模型
AQS的加锁过程
非公平锁的加锁过程
前提:线程A和线程B抢夺锁资源
1、线程A和线程B通过CAS的方式将state变量值从0改成1,谁成功了,谁就获得锁了
2、假设线程A成功了,此时线程B被封装成node对象
3、node对象的线程变量是线程B,互斥锁,waitStatus的值是0
4、将node对象放到双向链表的尾部,并且将线程的状态变成挂起
5、双向链表的头节点是个伪节点,伪节点中thread变量值为null
6、每当有新的node节点添加到链表中,前一个节点的waitStatus值从0变成-1,表示后面存在挂起的节点
加锁流程示意图: