这是题主在学习AQS阅读源码中遇到的问题。
nextWaiter是一个节点的属性,用于表示在等待队列中的模式或在条件队列中的下一个节点。在等待队列中,如果一个节点是独占模式,那么它的nextWaiter属性为null,如果是共享模式,那么它的nextWaiter属性为Node.SHARED。在条件队列中,nextWaiter属性表示下一个节点。
等待队列是一个FIFO队列,用于存储等待锁的线程。当一个线程请求锁时,如果锁已经被占用,那么这个线程会被封装成一个节点并加入到等待队列中。当锁被释放时,等待队列中的第一个节点会被唤醒并尝试获取锁。
条件队列是一个FIFO队列,用于存储等待某个条件的线程。当一个线程调用Condition.await()方法时,它会被封装成一个节点并加入到条件队列中。当另一个线程调用Condition.signal()方法时,条件队列中的第一个节点会被唤醒并尝试获取锁。
//每个处于等待状态的线程都可以是一个节点,并且每个节点是有很多状态的
static final class Node {
//每个节点都可以被分为独占模式节点或是共享模式节点,分别适用于独占锁和共享锁
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
//等待状态,这里都定义好了
//唯一一个大于0的状态,表示已失效,可能是由于超时或中断,此节点被取消。
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;
}
}