AQS:AbstractQueuedSynchronizer,抽象队列同步器。前面已经解析了部分AQS的源码,这里只是简单讲述下AQS的实现思想。
同步状态(state)的管理
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
AQS很巧妙的用到了volatile+compareAndSetState对同步状态的管理。【关键字synchronized 和volatile】中提到,volatile能够保证不同线程对共享变量操作的可见性,并且能够保证简单操作(set/get操作,但是i++这类的不行)原子性,但是不能保证共享变量在多个线程执行写操作时的线程安全。而在AQS中,所有多线程操作state的时候都是通过compareAndSetState实现的。
Node
static final class Node {
/** 两种模式 */
//共享模式
static final Node SHARED = new Node();
//独占模式
static final Node EXCLUSIVE = null;
/**waitstatus值的含义 */
//节点设置为取消状态
static final int CANCELLED = 1;
//后续节点需要被唤醒
static final int SIGNAL = -1;
//节点处于等待队列中,等待队列中的节点进入同步队列,状态会设置成0
static final int CONDITION = -2;
//共享可以传递给其他节点
static final int PROPAGATE = -3;
//状态字段,除了上面四种状态,还有一个0,表示默认状态
volatile int waitStatus;
//当前节点的前一节点
volatile Node prev;
//当前节点的后一节点
volatile Node next;
//当前节点对应的线程
volatile Thread thread;
//condition队列中的后一节点
Node nextWaiter;
//共享模式下等待,返回true
final boolean isShared() {
return nextWaiter == SHARED;
}
//返回当前节点的前一节点,为null则抛出异常
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
Node中有CLH同步队列和Condition等待队列的指向属性,所以Node在CLH同步队列和Condition等待队列上新增/删除操作都非常方便;Node中的thread标识节点对应的线程,并且线程的属性也存在Node中,这样对线程的操作就直接转换成对Node的操作,这样AQS只要维护好同步队列和等待队列即能保障对线程的管理。
CLH同步队列
新节点加入同步队列,通过CAS操作,将节点拼接到tail节点后,成为新的尾节点;节点从同步队列中删除时,只需要将其设置成head节点,并确定好next节点。
Condition等待队列
添加节点到等待队列中,会将原来lastWaiter的nextWaiter指向新增节点,然后将新增节点设置成lastWaiter;从等待队列中删除节点,将节点的nextWaiter置为null,(如果存在)删除节点前一节点的nextWaiter重新指向到删除节点的后一节点。
线程阻塞与唤醒
AQS中线程的使用与唤醒用的是LockSupport类中park/unpark方法,park/unpark可以阻塞或者唤醒指定的线程。
源码解析:
【AQS中ConditionObject(Condition接口实现)源码解析】
如果有写的不对的地方,请大家多多批评指正,非常感谢!