1. addWaiter设置为shared模式。
2. tryAcquire和tryAcquireShared的返回值不同,因此会多出一个判断过程
3. 在判断前驱节点是头节点后,调用了setHeadAndPropagate方法,而不是简单的更新一下头节点。
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
//创建一个共享模式的节点添加到队列中
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);//
就判断尝试获取锁
if (r >= 0) {//r>=0表示获取到了执行权限,这个时候因为state!=0,所以不会执行这段代码
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//阻塞线程
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
图解分析
加入这个时候有3个线程调用了await方法,由于这个时候state的值还不为0,所以这三个线程都会加入到AQS队列中。并且三个线程都处于阻塞状态