Java并发编程系列-AbstractQueuedSynchronizer (8)

该方法表示独享式获取同步状态,响应中断,源码如下:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { 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 { // 首先将当前线程封装成为Node节点,并保存到同步队列尾部 final Node node = addWaiter(Node.EXCLUSIVE); boolean failed = true; try { // 自旋,逻辑桶acquire for (;;) { final Node p = node.predecessor(); 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); } } }

解析:一开始就进行中断校验,如果未被中断则尝试独享式获取同步状态,获取失败后则封装线程为Node节点并保存到同步队列,然后自旋,逻辑与acquire种的acquireQueued方法逻辑一致,不再赘述。

tryAcquireNanos(int, long)

该方法表示独享式获取同步状态,响应中断,响应超时,源码如下:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { // 首先响应中断,进行中断校验,若被中断,抛出异常 if (Thread.interrupted()) throw new InterruptedException(); return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout);// 超时获取 } // 超时获取 private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { // 如果超时时间小于等于0,则直接超时,返回false if (nanosTimeout <= 0L) return false; final long deadline = System.nanoTime() + nanosTimeout;// 计算截止时间点 final Node node = addWaiter(Node.EXCLUSIVE);// 封装线程节点,并添加到同步队列 boolean failed = true; try { for (;;) {// 自旋 final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return true; } nanosTimeout = deadline - System.nanoTime();// 计算剩余超时时间 // 如果剩余超时时间小于等于0,这说明超时,返回false if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) &&// 将前置节点状态置为SIGNAL nanosTimeout > spinForTimeoutThreshold)// 剩余超时时间大于快速自旋时限(1000纳秒) LockSupport.parkNanos(this, nanosTimeout);// 限时阻塞当前线程,超时时间为剩余超时时间 // 再次响应中断,进行中断校验,若被中断直接抛出异常 if (Thread.interrupted()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } }

spinForTimeoutThreshold:这是系统内置的一个常量,设置为1000纳秒,这是一个很短的时间,如果要阻塞的剩余时间小于这个值,就没有必要再执行阻塞,直接进入快速自旋过程。

解析:整体逻辑基本与前面的两种类似,不同之处在于增加了针对超时时间处理的逻辑。

与acquireInterruptibly类似,一开始就进行中断校验,若被中断则抛出异常,否则尝试独享式获取同步状态,
获取成功,则返回true,如果获取失败,则将线程封装成Node节点保存到同步队列,然后计算截止时间点(当前时间+超时时间),
然后开始自旋,自旋的逻辑中前半部分与之前相同,只有在前置节点不是头节点或者获取同步状态失败的情况下逻辑发生了改变,
先计算剩余超时时间nanosTimeout(截止时间点-当前时间),然后将前置节点的状态置为SIGNAL,判断剩余超时时间是否大于
spinForTimeoutThreshold,如果大于则限时阻塞当前线程,否则快速自旋即可。

acquireShared(int)

该方法表示共享式获取同步状态,不响应中断,源码如下:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg); } }

解析:首先尝试共享式获取同步状态,如果获取失败(返回负值),则执行doAcquireShared方法。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwysj.html