在前面的文章中介绍了独占式同步状态的获取和释放以及共享式同步状态的获取和释放,在前面的文章中并没有介绍线程的阻塞和唤醒,在这篇文章中LZ将介绍在AQS中线程的阻塞和唤醒。
在线程获取同步状态失败后,会加入到CHL队列中去,并且该节点会自旋式的不断的获取同步状态,在获取同步状态的过程中,需要判断当前线程是否需要被阻塞。其主要方法在acquireQueued(final Node node, int arg)方法的定义里面:
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
通过这段代码可以看出,线程在获取同步状态失败后,并不是立马进入等待状态,而是需要判断当前线程是否需要被阻塞。检查是否需要阻塞的方法shouldParkAfterFailedAcquire(p, node),其定义如下:
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
// 获取前驱节点的等待状态
int ws = pred.waitStatus;
// 若果等待状态的值为SIGNAL,则返回true 表示当前线程需要等待
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
/*
* 前驱节点的状态>0,为CANCLE状态,表示该节点被中断或者超时,需要
* 从CHL中移除。
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {