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

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

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } }

该方法中调用了四个方法来完成功能,依次为:

tryAcquire(int):一个模板方法,授权子类来实现,主要用于尝试独享式获取同步状态。

addWaiter(Node):将当前线程封装成Node节点,添加到同步队列尾部

acquireQueued(Node,int):自旋获取锁,获取成功后返回等待过程中是否被中断过

selfInterrupt():进行中断处理

解析:首先尝试独享式获取同步状态,如果获取到了就结束,
如果未获取到则将线程封装成为Node节点并添加到同步队列尾部,然后自旋以获取同步状态,
一旦获取到同步状态,退出自旋,并返回当前线程在自旋期间是否被中断过,如果被中断过则再次自我中断,
为什么需要再次自我中断呢,这只是为了保留中断现场,因为在自旋结束进行中断校验时使用的是Thread.interrupted(),
该方法会导致中断状态被清除。

tryAcquire方法是一个模板方法,需要在AQS的子类中实现,默认的实现只是抛出了一个异常

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } }

addWaiter方法源码:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { private Node addWaiter(Node mode) { // 将当前线程与同步状态获取模式封装成为Node节点 Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure // 尝试快速进行一次enq操作,将新节点设置为同步地列尾节点, // 如果成功会结束方法但如果不成功,可以由下面的enq方法来执行, // 这个enq方法可以通过无限循环的方法直到执行成功 Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } // 将新节点添加到同步队列中 enq(node); return node; } // 将新节点添加到同步队列中 private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize // 这一步主要是针对同步队列未初始化时进行的初始化操作,初始化完成后下次循环就会执行新节点的添加操作 if (compareAndSetHead(new Node())) tail = head; } else { // 将之前的尾节点设置为新节点的前节点,然后原子更新尾节点为新节点 node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } }

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

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