staticfinalint CANCELLED = 1; /** waitStatus value to indicate successor's thread needs unparking */ staticfinalint SIGNAL = -1; /** waitStatus value to indicate thread is waiting on condition */ staticfinalint CONDITION = -2; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate */ staticfinalint PROPAGATE = -3; /** * Status field, taking on only the values: * SIGNAL: The successor of this node is (or will soon be) * blocked (via park), so the current node must * unpark its successor when it releases or * cancels. To avoid races, acquire methods must * first indicate they need a signal, * then retry the atomic acquire, and then, * on failure, block. * CANCELLED: This node is cancelled due to timeout or interrupt. * Nodes never leave this state. In particular, * a thread with cancelled node never again blocks. * CONDITION: This node is currently on a condition queue. * It will not be used as a sync queue node * until transferred, at which time the status * will be set to 0. (Use of this value here has * nothing to do with the other uses of the * field, but simplifies mechanics.) * PROPAGATE: A releaseShared should be propagated to other * nodes. This is set (for head node only) in * doReleaseShared to ensure propagation * continues, even if other operations have * since intervened. * 0: None of the above * * The values are arranged numerically to simplify use. * Non-negative values mean that a node doesn't need to * signal. So, most code doesn't need to check for particular * values, just for sign. * * The field is initialized to 0 for normal sync nodes, and * CONDITION for condition nodes. It is modified using CAS * (or when possible, unconditional volatile writes). */ volatileint waitStatus;
// “获取”类型操作(比如获取锁)的入口 /** * Acquires in exclusive mode, ignoring interrupts. Implemented * by invoking at least once {@link #tryAcquire}, * returning on success. Otherwise the thread is queued, possibly * repeatedly blocking and unblocking, invoking {@link * #tryAcquire} until success. This method can be used * to implement method {@link Lock#lock}. * * @param arg the acquire argument. This value is conveyed to * {@link #tryAcquire} but is otherwise uninterpreted and * can represent anything you like. */ publicfinalvoid(int arg){ if (!tryAcquire(arg) && // ① 先尝试进行获取操作(也就是修改内部的状态),如果成功则不会进行后续操作 acquireQueued( addWaiter(Node.EXCLUSIVE), arg) // ② 如果上一步获取失败(也就是修改内部状态失败)则先尝试将当前线程构造为等待队列的节点从队尾入队 ) // ③ 然后再尝试进行获取操作 selfInterrupt(); // ④ 如果在上一步的进队尝试获取操作返回了true,并且过程中发生了中断,则在此进行中断 }
// 上边 ① 处:tryAcquire(arg) 留给子类实现 /** * Attempts to acquire in exclusive mode. This method should query * if the state of the object permits it to be acquired in the * exclusive mode, and if so to acquire it. * * <p>This method is always invoked by the thread performing * acquire. If this method reports failure, the acquire method * may queue the thread, if it is not already queued, until it is * signalled by a release from some other thread. This can be used * to implement method {@link Lock#tryLock()}. * * <p>The default * implementation throws {@link UnsupportedOperationException}. * * @param arg the acquire argument. This value is always the one * passed to an acquire method, or is the value saved on entry * to a condition wait. The value is otherwise uninterpreted * and can represent anything you like. * @return {@code true} if successful. Upon success, this object has * been acquired. * @throws IllegalMonitorStateException if acquiring would place this * synchronizer in an illegal state. This exception must be * thrown in a consistent fashion for synchronization to work * correctly. * @throws UnsupportedOperationException if exclusive mode is not supported */ protectedbooleantryAcquire(int arg){ thrownew UnsupportedOperationException(); }
// 上边的 shouldParkAfterFailedAcquire 里面并不进行真正的 park,而是将传入的前驱节点设置为 SIGNAL 也就是前驱在释放后需要通知后边的节点 /** * Checks and updates status for a node that failed to acquire. * Returns true if thread should block. This is the main signal * control in all acquire loops. Requires that pred == node.prev. * * @param pred node's predecessor holding status * @param node the node * @return {@code true} if thread should block */ privatestaticbooleanshouldParkAfterFailedAcquire(Node pred, Node node){ int ws = pred.waitStatus; // 获得传入的前驱节点的状态 if (ws == Node.SIGNAL) // 假如传入的前驱节点的状态为 SIGNAL 则直接返回 true,true就意味着当前节点需要等待,SIGNAL 的意思是当前节点进行了释放操作后需要通知后继节点 /* * This node has already set status asking a release * to signal it, so it can safely park. */ returntrue; // 如果传入的前驱节点的状态大于 0 也就是 CANCELLED 这个状态(因为只有这个状态是大于0的) if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ do { 大专栏AbstractQueuedSynchronizer笔记 node.prev = pred = pred.prev; // 则将当前节点的前驱设置为前驱的前驱,也就是将传入的前驱节点摘掉 } while (pred.waitStatus > 0); pred.next = node; } // 否则当前传入的前驱节点的状态要莫是 0 要莫是 PROPAGATE 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. */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); // 用CAS方式将当前传入的前驱节点的状态设置为 SIGNAL,也就是前驱释放了需要通知当前节点 } returnfalse; }
1 2 3 4 5 6 7 8 9 10
// 真正执行 park /** * Convenience method to park and then check if interrupted * * @return {@code true} if interrupted */ privatefinalbooleanparkAndCheckInterrupt(){ LockSupport.park(this); return Thread.interrupted(); }
// "释放"操作, /** * Releases in exclusive mode. Implemented by unblocking one or * more threads if {@link #tryRelease} returns true. * This method can be used to implement method {@link Lock#unlock}. * * @param arg the release argument. This value is conveyed to * {@link #tryRelease} but is otherwise uninterpreted and * can represent anything you like. * @return the value returned from {@link #tryRelease} */ publicfinalbooleanrelease(int arg){ // tryRelease 交给子类实现 if (tryRelease(arg)) { // 如果释放操作成功了 Node h = head; // 等待队列头节点 if (h != null && h.waitStatus != 0) // 如果头节点存在,并且其状态不为 0 unparkSuccessor(h); // 那么就 unparkSuccessor returntrue; } returnfalse; }
// 唤醒给定节点的后继节点 /** * Wakes up node's successor, if one exists. * * @param node the node */ privatevoidunparkSuccessor(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; // 如果给定的当前节点的状态是小于0的,也就是不是 CANCELLED 或者 0,也就是“正常”的状态 if (ws < 0) compareAndSetWaitStatus(node, ws, 0); // 那么就用CAS方式把给定的当前节点的状态设置为 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; // 给定节点的后继节点 // 如果给定节点的后继节点是空或者其状态是 CANCELLED if (s == null || s.waitStatus > 0) { s = null; // 那么就将给定节点的后继节点设置为空 // 然后从等待队列的尾部向前找,每次找到状态小于 0 的节点就将其设置为给定节点的后继,直到到了给定后继节点为止,也就是找到给定节点的后继节点后边第一个“正常”状态的节点设置为后继节点 for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 如果经过了上面的操作到了这里给定节点的后继节点不是空的话 if (s != null) LockSupport.unpark(s.thread); // 则 unpark 现在的定节点的后继节点中存储的 thread 对象 }
获取(共享式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 共享式获取 /** * Acquires in shared mode, ignoring interrupts. Implemented by * first invoking at least once {@link #tryAcquireShared}, * returning on success. Otherwise the thread is queued, possibly * repeatedly blocking and unblocking, invoking {@link * #tryAcquireShared} until success. * * @param arg the acquire argument. This value is conveyed to * {@link #tryAcquireShared} but is otherwise uninterpreted * and can represent anything you like. */ publicfinalvoidacquireShared(int arg){ if (tryAcquireShared(arg) < 0) // tryAcquireShared 交给子类实现,尝试做获取操作 doAcquireShared(arg); // 假如上面的获取操作失败了,则 doAcquireShared ,在里面是如等待队列并根据条件尝试再获取 }
/** * Sets head of queue, and checks if successor may be waiting * in shared mode, if so propagating if either propagate > 0 or * PROPAGATE status was set. * * @param node the node * @param propagate the return value from a tryAcquireShared */ privatevoidsetHeadAndPropagate(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. */ // 然后,判断传入的 propagate(也就是剩余资源数)是否大于0,或者原头节点为空或原头节点状态小于0(意味着状态为SIGNAL或PROPAGATE)或者经过上边的设置头节点后的新的头节点为空或者经过上边的设置头节点后的新的头节点状态小于0(意味着状态为SIGNAL或PROPAGATE) if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { // 获得当前节点的后继节点 Node s = node.next; // 如果后继节点为空或者后继节点为共享类型的节点 if (s == null || s.isShared()) // 那么就 doReleaseShared 这里面是做了保证后继节点的后继节点也能被唤醒,唤醒了就能参与“获取”操作(因为共享型的获取不只自己能获取,也要让后边的人也能获取才行,这样才是共享的)其实复用了“释放”操作得一部分逻辑 doReleaseShared(); } }
/** * Release action for shared mode -- signals successor and ensures * propagation. (Note: For exclusive mode, release just amounts * to calling unparkSuccessor of head if it needs signal.) */ privatevoiddoReleaseShared(){ /* * 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) { // 如果头节点的状态为 SIGNAL(也就是要自己等待然后去尝试唤醒后继节点) int ws = h.waitStatus; if (ws == Node.SIGNAL) { // 如果自己等待失败了就反复重试 if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases // 直到自己成功变为等待状态了,就唤醒后继节点 unparkSuccessor(h); } // 头节点为等待状态(ws == 0)时,将自己设置为 PROPAGATE (传播状态,这里就是在 setHeadAndPropagate 中调用 doReleaseShared 的目的)这个设置是反复重试直到成功的 elseif (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } // 反复的条件:如果头节点发生过改变 if (h == head) // loop if head changed break; } }
释放(共享式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/** * Releases in shared mode. Implemented by unblocking one or more * threads if {@link #tryReleaseShared} returns true. * * @param arg the release argument. This value is conveyed to * {@link #tryReleaseShared} but is otherwise uninterpreted * and can represent anything you like. * @return the value returned from {@link #tryReleaseShared} */ publicfinalbooleanreleaseShared(int arg){ if (tryReleaseShared(arg)) { // tryReleaseShared 交给子类实现 doReleaseShared(); // 如果尝试释放成功了则 doReleaseShared ? returntrue; } returnfalse; }