AbstractQueuedLongSynchronizer 即AQS。 通过一个FIFO的双向队列实现的一个同步器。
- 通过源码了解AQS提供的方法,可以进一步加深对锁实现的理解。AQS是可重入锁,可重入读写锁的一个基础支撑,提供了一系列的方法。
-
// * <pre> * +------+ prev +-----+ +-----+ * head | | <---- | | <---- | | tail * +------+ +-----+ +-----+ * </pre> public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { private static final long serialVersionUID = 7373984972572414691L; /** * Creates a new {@code AbstractQueuedSynchronizer} instance * with initial synchronization state of zero. */ protected AbstractQueuedSynchronizer() { } // 队列 头结点 volatile 修饰保证了可见性 transient 保证了序列化时不序列化该字段 private transient volatile Node head; // 对列 尾结点 private transient volatile Node tail; // 同步状态 private volatile int state; // 为cas 操作提供支持 unsafe 负责CAS 操作 private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long stateOffset; private static final long headOffset; private static final long tailOffset; private static final long waitStatusOffset; private static final long nextOffset; // 内部静态节点类 static final class Node { /** Marker to indicate a node is waiting in shared mode * 标记该节点时需要获取的是共享模式锁 */ static final Node SHARED = new Node(); /** Marker to indicate a node is waiting in exclusive mode ** 标记该节点是等待获取独占模式锁 */ static final Node EXCLUSIVE = null; /** waitStatus value to indicate thread has cancelled */ // 取消状态 当线程取消尝试获取锁,等待状态置为取消。 // 节点处于该状态,则当前节点会被跳过。 static final int CANCELLED = 1; /** waitStatus value to indicate successor's thread needs unparking * waitStatus值,指示后续线程需要释放 */ static final int SIGNAL = -1; /** waitStatus value to indicate thread is waiting on condition * 指示线程正在等待条件 */ static final int CONDITION = -2; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate * 指示下一个acquireShared应该*无条件传播 */ static final int PROPAGATE = -3; // 等待状态 volatile int waitStatus; // 前一个节点 volatile Node prev; // 下一个节点 volatile Node next; // 当前节点持有的线程 volatile Thread thread; // 下一个等待者 Node nextWaiter; // 判断下一个等待者是否是共享模式节点 final boolean isShared() { return nextWaiter == SHARED; } //获取当前节点的前一个节点 final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } // 构造函数,仅用于创建头结点和共享模式标记 // 这里可以看出初始化头结点是一个空节点。 Node() { // Used to establish initial head or SHARED marker } // 构造函数,用于创建等待者节点 Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } // 构造函数,绑定线程和等待状态来创建节点 Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } } // AQS类 方法 // 通过使用unsafed CAS 来设置state的值 protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } // 插入节点,如果节点没有初始化,则先初始化头结点。 // 初始化完成 ,则将使用尾插法插入node节点,返回node节点的头结点。 // 如果第一次调用,则返回的就是头结点。 private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize // CAS 设置头结点 if (compareAndSetHead(new Node())) tail = head; } else { // node 上一个节点设置为当前的尾结点 node.prev = t; // CAS设置node为尾结点 if (compareAndSetTail(t, node)) { // node设置为尾结点成功,则设置之前尾结点的下一个节点时node节点。 //这样就构成了一个双向的链表 t.next = node; return t; } } } } // 添加等待节点 // mode 锁模式,独占和共享 private Node addWaiter(Node mode) { //构造一个持有当前线程,指定模式的节点 Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; //尾结点不为空,则尾插法插入node节点。 //尾结点不为空,说明该队列已经初始化完成 if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } // 尾结点为空,则初始化对列,尾插法插入node节点 enq(node); //返回 持有当前线程的节点,也是双向队列的尾结点 return node; } //设置头结点 node节点设置为头结点 ,头结点持有的线程置为null // 前向指针指向null private void setHead(Node node) { head = node; node.thread = null; node.prev = null; } // 尝试唤醒继任节点 private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ int ws = node.waitStatus; // node 节点的等待状态小于0,则设置其等待状态为0 // 0 代表是等待状态之外的其他状态 if (ws < 0) compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ // 获取下一个节点 Node s = node.next; // 没有下一个节点或者下一个节点持有的线程已被取消 if (s == null || s.waitStatus > 0) { s = null; //从后向前循环查找等待状态小于等于0的节点赋值给s,至到node节点终止 // 从后往前找到node节点第一个未被取消的继任者 // 为何这里不从node节点开始,从前往后查找???? 因为新节点采用尾插法插入,所以从后向前找,避免产生不可预料行为 for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; //找到则唤醒节点的线程 if (s != null) LockSupport.unpark(s.thread); } // 共享模式锁的释放 private void doReleaseShared() { /* * Ensure that a release propagates, even if there are other * in-progress acquires/releases. This proceeds in the usual * way of trying to unparkSuccessor of head if it needs * signal. But if it does not, status is set to PROPAGATE to * ensure that upon release, propagation continues. * Additionally, we must loop in case a new node is added * while we are doing this. Also, unlike other uses of * unparkSuccessor, we need to know if CAS to reset status * fails, if so rechecking. */ for (;;) { Node h = head; // 头节点不为空,且头节点不等于尾节点 if (h != null && h != tail) { int ws = h.waitStatus; // 表示后继者需要释放 if (ws == Node.SIGNAL) { //设置节点等待状态为0 if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases // 设置成功,则唤醒后继者 unparkSuccessor(h); } // 等待状态为0,设置等待状态为-3失败则返回开始处继续循环 else if (ws == 0 &&!compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } //等于头结点结束循环 if (h == head) // loop if head changed break; } } private void setHeadAndPropagate(Node node, int propagate) { Node h = head; // Record old head for check below //设置头结点 setHead(node); /* * Try to signal next queued node if: * Propagation was indicated by caller, * or was recorded (as h.waitStatus either before * or after setHead) by a previous operation * (note: this uses sign-check of waitStatus because * PROPAGATE status may transition to SIGNAL.) * and * The next node is waiting in shared mode, * or we don't know, because it appears null * * The conservatism in both of these checks may cause * unnecessary wake-ups, but only when there are multiple * racing acquires/releases, so most need signals now or soon * anyway. */ // 原来的头结点为空,或者其等待状态小于0 或 // 现在的头结点为空 或者等待状态小于0 if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { Node s = node.next; //下一个节点为空或者是共享模式的则尝试释放共享锁 if (s == null || s.isShared()) doReleaseShared(); } } // 设置node节点为取消状态,则该节点不再去获取锁 private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; // 节点绑定线程置为空 node.thread = null; // Skip cancelled predecessors Node pred = node.prev; // 跳过已经取消的节点 while (pred.waitStatus > 0) // 设置node的前一个节点为pred的前一个节点 node.prev = pred = pred.prev; // predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel // or signal, so no further action is necessary. // pred的下一个节点 Node predNext = pred.next; // Can use unconditional write instead of CAS here. // After this atomic step, other Nodes can skip past us. // Before, we are free of interference from other threads. // 节点状态设置为已取消 node.waitStatus = Node.CANCELLED; // If we are the tail, remove ourselves. // node 节点时尾结点,设置pred上一个节点为尾节点 if (node == tail && compareAndSetTail(node, pred)) { // 设置pred的下一个节点为null compareAndSetNext(pred, predNext, null); } else { // If successor needs signal, try to set pred's next-link // so it will get one. Otherwise wake it up to propagate. int ws; // if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) { Node next = node.next; if (next != null && next.waitStatus <= 0) compareAndSetNext(pred, predNext, next); } else { unparkSuccessor(node); } // node下一个节点指向自己,则此时没有节点指向node,node不可达即可被回收 // 为何不直接置为null node.next = node; // help GC } } //尝试获取失败后 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; // 线程应该被阻塞 if (ws == Node.SIGNAL) /* * This node has already set status asking a release * to signal it, so it can safely park. */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ //从pred开始循环向前找到一个未被取消的节点 do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); //找到的pred 的下一个节点置为node。 pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. */ //等待状态为0或者 PROPAGATE,则CAS尝试将状态设置为 SIGNAL // compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; } /** * Convenience method to interrupt current thread. */ static void selfInterrupt() { // 线程中断 Thread.currentThread().interrupt(); } // 优雅的挂起线程的方法,返回线程是否中断成功 private final boolean parkAndCheckInterrupt() { // 挂起线程 LockSupport.park(this); return Thread.interrupted(); } /** * Acquires in exclusive uninterruptible mode for thread already in * queue. Used by condition wait methods as well as acquire. * * @param node the node * @param arg the acquire argument * @return {@code true} if interrupted while waiting */ // 独占模式获取在队列里的线程,用于wait 或者acquire 方法 final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); //node 节点的前一个节点为头节点 尝试获取锁成功 if (p == head && tryAcquire(arg)) { // 当前节点的线程获取锁成功,头节点设置为 node setHead(node); //原来的头节点next指向null p.next = null; // help GC failed = false; // 返回false return interrupted; } // 获取失败后是否应该挂起 且 尝试挂起 返回是否中断成功 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } //尝试获取独占模式对象,留给子类实现 protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } //获取锁 public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //尝试获取锁失败,中断当前线程 selfInterrupt(); } //非中断模式获取锁 // private void doAcquireInterruptibly(int arg) throws InterruptedException { // 当前线程以独占模式加入等待队列,返回持有当前线程的节点 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; } // 如果node节点持有的当前线程应该被挂起且已经被中断则抛出中断异常 // 中断异常 ,那么实现了非中断模式获取锁,如果使用此方法, // 那么 获取锁的线程不能被中断 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } // 带有超时时间获取锁,一旦超时则返回获取失败 private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { 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(); if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); if (Thread.interrupted()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } //共享模式尝试获取锁 private void doAcquireShared(int arg) { // 共享模式加入等待队列 final Node node = addWaiter(Node.SHARED); boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); //node 的前一个节点等于头节点 if (p == head) { // 尝试获取共享锁 int r = tryAcquireShared(arg); if (r >= 0) { //设置头节点及其等待状态 setHeadAndPropagate(node, r); p.next = null; // help GC if (interrupted)// 调用中断方法 selfInterrupt(); failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } //锁释放 子类实现 protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); } // 尝试获取共享锁 protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } //尝试获取锁 public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //获取失败,线程中断 selfInterrupt(); } // 释放锁 public final boolean release(int arg) { // 尝试释放锁 if (tryRelease(arg)) { Node h = head; //头节点不为空,且头节点等待状态不等于0 唤醒下一个等待者 if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } // 尝试获取共享锁 public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg); } // 释放共享锁 public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; } // 是否还有排队的线程 public final boolean hasQueuedThreads() { return head != tail; } // 是否有线程获取过同步器 public final boolean hasContended() { return head != null; } //返回等待最久的线程 public final Thread getFirstQueuedThread() { // handle only fast path, else relay return (head == tail) ? null : fullGetFirstQueuedThread(); } // 查找最靠近头节点的节点持有的线程 private Thread fullGetFirstQueuedThread() { /* * The first node is normally head.next. Try to get its * thread field, ensuring consistent reads: If thread * field is nulled out or s.prev is no longer head, then * some other thread(s) concurrently performed setHead in * between some of our reads. We try this twice before * resorting to traversal. */ Node h, s; Thread st; // 尝试获取头节点的下一个节点的线程 if (((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.thread) != null) || ((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.thread) != null)) return st; /* * Head's next field might not have been set yet, or may have * been unset after setHead. So we must check to see if tail * is actually first node. If not, we continue on, safely * traversing from tail back to head to find first, * guaranteeing termination. */ Node t = tail; Thread firstThread = null; // 从后向前循环查找节点持有的线程 // 不是从前往后查找的原因在于有可能其他线程在设置头节点, // 一种情况当前线程获取的头节点时原来的头节点,当获取头节点的下一个节点时 // 此时有另一个线程已经将原来头节点的next指向null,那么将会导致此次查找失败。 //这也是双向链表的一个好处。头节点在设置,从尾节点查找,避免产生冲突。 while (t != null && t != head) { Thread tt = t.thread; if (tt != null) firstThread = tt; t = t.prev; } return firstThread; } //返回给定线程是否正在排队 public final boolean isQueued(Thread thread) { if (thread == null) throw new NullPointerException(); for (Node p = tail; p != null; p = p.prev) if (p.thread == thread) return true; return false; } //是否有一个排他模式的线程在等待获取锁 final boolean apparentlyFirstQueuedIsExclusive() { Node h, s; return (h = head) != null && (s = h.next) != null && !s.isShared() && s.thread != null; } // 是否有其他线程等待时间比当前线程更久 // 用来实现公平锁 public final boolean hasQueuedPredecessors() { // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } // 返回对列长度 public final int getQueueLength() { int n = 0; for (Node p = tail; p != null; p = p.prev) { if (p.thread != null) ++n; } return n; } //返回队列持有的线程集合 public final Collection<Thread> getQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { Thread t = p.thread; if (t != null) list.add(t); } return list; } //返回排他模式的线程集合 public final Collection<Thread> getExclusiveQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { if (!p.isShared()) { Thread t = p.thread; if (t != null) list.add(t); } } return list; } // 获取共享模式的线程集合 public final Collection<Thread> getSharedQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { if (p.isShared()) { Thread t = p.thread; if (t != null) list.add(t); } } return list; } }