十五、condition之初识await方法

59 阅读2分钟

初识await方法

调用await方法后,执行流程:

  1. 判断线程是否中断,如果中断抛出异常
  2. 将当前线程放入condition链表中,并且删除链表中状态不是CONDITION的节点
  3. 释放所有的锁资源,并且返回重入的次数
  4. 如果当前线程不持有锁资源,抛出异常,并且将condition链表中的节点状态设置为CANCELLED
  5. 如果当前线程没有在AQS队列中,则挂起
public final void await() throws InterruptedException {
	// 如果线程中断,则抛出中断异常
	if (Thread.interrupted())
		throw new InterruptedException();
	// 将当前线程加入到condition单向链表中,并且删除链表中状态不是-2的节点
  // 对单向链表做一次垃圾节点清理
	Node node = addConditionWaiter();
	// 释放所有锁资源,并且返回重入的次数
	int savedState = fullyRelease(node);
	int interruptMode = 0;
	// 如果线程不在AQS队列中,则挂起。
	// 有这样一种情况,线程在执行完fullyRelease方法后,时间片用完了,另一个线程拿到锁资源
	// 并且另一个线程调用了signal方法,signal方法会将当前线程从condition队列中转移到AQS队列中。
  // 此时,如果当前线程获得cpu资源继续执行,是不需要执行LockSupport.park(this)方法将其挂起的
	while (!isOnSyncQueue(node)) {
		LockSupport.park(this);
		if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
			break;
	}
	if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
		interruptMode = REINTERRUPT;
	if (node.nextWaiter != null)
		unlinkCancelledWaiters();
	if (interruptMode != 0)
		reportInterruptAfterWait(interruptMode);
}
private Node addConditionWaiter() {
	Node t = lastWaiter;
	// 如果尾节点不为空,并且尾节点的waitStatus值不为-2,说明节点不正常
	if (t != null && t.waitStatus != Node.CONDITION) {
		// 删除掉condition链表中不正常的节点
		unlinkCancelledWaiters();
		t = lastWaiter;
	}
	Node node = new Node(Thread.currentThread(), Node.CONDITION);
	if (t == null)
		// 链表中没有节点,当前线程作为第一个节点
		firstWaiter = node;
	else
		// 当前线程添加到链表中
		t.nextWaiter = node;
	// 尾节点指向当前线程
	lastWaiter = node;
	return node;
}
// 释放所有的锁资源,并且返回重入次数
final int fullyRelease(Node node) {
	boolean failed = true;
	try {
		int savedState = getState();
		// release方法中传入state的值,表示释放所有锁资源
		if (release(savedState)) {
			failed = false;
			return savedState;
		} else {
			// 当前线程没持有锁资源
			throw new IllegalMonitorStateException();
		}
	} finally {
		if (failed)
			node.waitStatus = Node.CANCELLED;
	}
}