共享式获取
void acquireShared(int arg)
//同步器调用tryAcquireShared获取同步状态,当返回值大于0 时,表示能够获取同步状态。
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
int tryAcquireShared(arg)
//如果获取同步状态失败,那么返回的就是负数。
//在acquireShared 方法中,只有获取同步状态失败,才能执行doAcquireShared 方法
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
void doAcquireShared(int arg)
/**
* Acquires in shared uninterruptible mode.
* @param arg the acquire argument
*/
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//如果当前节点的前驱节点是头结点时,尝试获取同步状态,
if (p == head) {
int r = tryAcquireShared(arg);
//如果返回值 r >= 0,表示该次获取同步状态成功并从自旋过程中退出。
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);
}
}
void setHeadAndPropagate(Node node, int propagate)
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // 记录旧的头节点
//将当前操作的节点设置为头结点
setHead(node);
//如果propagate > 0,表示当前同步状态获取成功;
//或者waitStatus 被设置为PROPAGATE(PROPAGATE = -3;)。
//注意这里h == null || h.waitStatus < 0
//与 (h = head) == null || h.waitStatus < 0的区别:
//第一个判断是在线程执行 setHead(node);方法之后,才走到这里。
//第二个判断是线程执行 setHead(node);方法之前,就已经走到这里了。
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
//向后传播
Node s = node.next;
// 如果下个节点不存在 或者 是在共享模式下等待,
//那么我们都要执行doReleaseShared();方法,
//释放同步状态。
if (s == null || s.isShared())
doReleaseShared();
}
}
boolean isShared()
/**
* Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
void setHead(Node node)
/**
* Sets head of queue to be node, thus dequeuing. Called only by
* acquire methods. Also nulls out unused fields for sake of GC
* and to suppress unnecessary signals and traversals.
*
* @param node the node
*/
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
void 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.)
*/
private void doReleaseShared() {
for (;;) {
//节点h表示头结点
Node h = head;
//头结点不为空 且 头结点和尾结点不是同一个节点
//也就是,同步队列中不只一个节点。
if (h != null && h != tail) {
//ws是当前头节点的waitStatus的值
int ws = h.waitStatus;
//如果ws的值表示可唤醒后继节点
if (ws == Node.SIGNAL) {
如果CAS操作设置节点waitStatus的值为0 失败
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
//从for 循环头开始自旋
continue; // loop to recheck cases
//只有当头结点的waitStatus的值为SIGNAL,且CAS修改waitStatus成功,
// 才可以唤醒后继节点
unparkSuccessor(h);
}
//如果waitStatus == 0 且CAS修改节点waitStatus值为PROPAGATE失败
//从for 循环头开始自旋
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
//unparkSuccessor(h);传入的参数是h,
//如果该方法执行成功,那么h所指的就应该是当前的头结点
if (h == head) // loop if head changed
break;
}
}
void unparkSuccessor(Node node)
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
//如果waitStatus值是负的,那么就要尝试在唤醒之前,修改
//如果没有修改成功也没没关系
//如果status被等待中的线程修改也可以
//如果此时waitStatus<0,使用CAS将waitStatus设为0,
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//找到当前节点的后继节点s
Node s = node.next;
// 如果s为空(node不存在后继节点)或者s.waitStatus > 0(s节点已经被唤醒了)
if (s == null || s.waitStatus > 0) {
//此时再将s置位空,从尾结点开始,逆向查找,
//直到找到waitStatus<=0 的节点(也就是找到第一个非空节点);
//判断当前的额非空节点t的waitStatus <=0,如果是这样,说明t还没有被唤醒。
//将t的值给s
//再次判断s是否为空,以防别的线程已经修改过。
//之后再执行unpark,获取同步状态。
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
全图
共享式释放
boolean releaseShared(int arg)
//在共享模式下释放同步状态,该方法释放完同步状态之后,会唤醒后续处于等待状态的节点。
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
boolean tryReleaseShared(int arg)
共享模式下release是否允许一个等待中的acquire(共享的或排他的)获取后继节点。
如果是,返回true
否则返回false;
简而言之,就是是否允许对后继节点的获取。
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}