十二、ReentrantLock加锁流程之lockInterruptibly方法

65 阅读1分钟

ReentrantLock加锁流程之lockInterruptibly方法

lockInterruptibly方法的流程是:线程放入AQS链表中,如果前一个节点不是head节点,则挂起;如果是,则尝试获取锁资源。线程被挂起后,在两种情况下会被唤醒,第一种是正常被唤醒,此时可以拿到锁资源;第二种是被中断唤醒,此时抛出中断异常。

public void lockInterruptibly() throws InterruptedException {
	sync.acquireInterruptibly(1);
}

public final void acquireInterruptibly(int arg)
		throws InterruptedException {
	if (Thread.interrupted())
		throw new InterruptedException();
	if (!tryAcquire(arg))
		doAcquireInterruptibly(arg);
}

private void doAcquireInterruptibly(int arg)
	throws InterruptedException {
	// 线程放入AQS链表中
	final Node node = addWaiter(Node.EXCLUSIVE);
	boolean failed = true;
	try {
		for (;;) {
			final Node p = node.predecessor();
			// 如果前一个节点是head节点,则尝试获取锁资源
			if (p == head && tryAcquire(arg)) {
				setHead(node);
				p.next = null; // help GC
				failed = false;
				return;
			}
			// 线程被挂起,但是被中断会唤醒,抛出中断异常
			if (shouldParkAfterFailedAcquire(p, node) &&
				parkAndCheckInterrupt())
				throw new InterruptedException();
		}
	} finally {
		if (failed)
			cancelAcquire(node);
	}
}