Java并发编程-AbstractQueuedSynchronizer源码分析(7)
- UID
- 1066743
|
Java并发编程-AbstractQueuedSynchronizer源码分析(7)
public final void acquireInterruptibly(int arg)该方法提供获取状态能力,当然在无法获取状态的情况下会进入sync队列进行排队,这类似acquire,但是和acquire不同的地方在于它能够在外界对当前线程进行中断的时候提前结束获取状态的操作,换句话说,就是在类似synchronized获取锁时,外界能够对当前线程进行中断,并且获取锁的这个操作能够响应中断并提前返回。一个线程处于synchronized块中或者进行同步I/O操作时,对该线程进行中断操作,这时该线程的中断标识位被设置为true,但是线程依旧继续运行。
如果在获取一个通过网络交互实现的锁时,这个锁资源突然进行了销毁,那么使用acquireInterruptibly的获取方式就能够让该时刻尝试获取锁的线程提前返回。而同步器的这个特性被实现Lock接口中的lockInterruptibly方法。根据Lock的语义,在被中断时,lockInterruptibly将会抛出InterruptedException来告知使用者。
[url=][/url]
01 public final void acquireInterruptibly(int arg)02 throws InterruptedException {03 if (Thread.interrupted())04 throw new InterruptedException();05 if (!tryAcquire(arg))06 doAcquireInterruptibly(arg);07 }08 09 private void doAcquireInterruptibly(int arg)10 throws InterruptedException {11 final Node node = addWaiter(Node.EXCLUSIVE);12 boolean failed = true;13 try {14 for (;;) {15 final Node p = node.predecessor();16 if (p == head && tryAcquire(arg)) {17 setHead(node);18 p.next = null; // help GC19 failed = false;20 return;21 }22 // 检测中断标志位23 if (shouldParkAfterFailedAcquire(p, node) &&24 parkAndCheckInterrupt())25 throw new InterruptedException();26 }27 } finally {28 if (failed)29 cancelAcquire(node);30 }31 }[url=][/url]
上述逻辑主要包括:
1. 检测当前线程是否被中断;
判断当前线程的中断标志位,如果已经被中断了,那么直接抛出异常并将中断标志位设置为false。
2. 尝试获取状态;
调用tryAcquire获取状态,如果顺利会获取成功并返回。
3. 构造节点并加入sync队列;
获取状态失败后,将当前线程引用构造为节点并加入到sync队列中。退出队列的方式在没有中断的场景下和acquireQueued类似,当头结点是自己的前驱节点并且能够获取到状态时,即可以运行,当然要将本节点设置为头结点,表示正在运行。
4. 中断检测。
在每次被唤醒时,进行中断检测,如果发现当前线程被中断,那么抛出InterruptedException并退出循环。 |
|
|
|
|
|