说明:本文是我对自己学习知识的一个简单总结,可能存在许多不足,我希望通过此方式来回顾知识,加强理解,也希望大家能指出文中的错误与不足,互相学习,谢谢。
AQS(AbstractQueuedSynchronizer)核心分析
首先看一下类图:
- AbstractOwnableSynchronizer是个抽象类,以独占模式设置当前持有的线程。
- AbstractQueuedSynchronizer从名字来看是抽象的同步队列,这个队列叫做CLH锁队列,CLH锁通常使用的是自旋锁,并且是双向的队列,AQS中还有一种队列叫做条件队列,存储的是"处于等待状态的线程"。CLH队列结构如下:
1. Node
接下来看下AQS里面的一个静态内部类,Node,这个类是存储在队列中的基础结构,是用来存储队列中数据的节点,源码如下:
static final class Node {
/**
* 节点为共享模式标记
* */
static final Node SHARED = new Node();
/**
* 节点为独占模式标记
*/
static final Node EXCLUSIVE = null;
/**
* 节点为取消状态
* */
static final int CANCELLED = 1;
/**
* 只要队列前置节点释放锁,为SIGNAL状态的后继节点的线程得以运行。
*/
static final int SIGNAL = -1;
/**
* 条件队列状态标识
*/
static final int CONDITION = -2;
/**
* 表示下一次共享式同步状态获取将会被无条件地传播下去
*/
static final int PROPAGATE = -3;
/**
* 标记当前节点的信号量状态 (1,0,-1,-2,-3)5种状态
*/
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;
}
}