


尝试获取共享资源, 返回值为整数, 负数为失败, 0为成功, 但是其他线程无法再成功, 正数为成功, 其他线程也可以成功。
由于共享锁允许多个线程同时获取成功,因此可以用 返回值代表还能有几个线程可以继续获取资源,但并不是强制性的。
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);
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);
}
}
获取资源成功后,需要执行setHeadAndPropagate(node, r);
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
//唤醒队列的节点
if (s == null || s.isShared())
doReleaseShared();
}
}

private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
//signal需要唤醒阻塞线程
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
对头节点的处理。
if (h == head) 的判断则说明如果处理过程中头结点发生变化则需要重试。

private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
在尝试获取资源和阻塞结束后检测到中断后抛出异常。
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
//检测超时时间
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
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);
}
}