Semaphore 有点像一个停车场,permits 就好像停车位数量,当线程获得了 permits 就像是获得了停车位,然后停车场显示空余车位减一
此处是不公平的实现
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
//构造方法,permits等于资源数
NonfairSync(int permits) {
super(permits);
}
// Semaphore 方法, 方便阅读, 放在此处
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// AQS 继承过来的方法, 方便阅读, 放在此处
// 获得可打断的共享锁
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
//如果发生中断则抛出异常
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
//如果资源不够,进入此方法
doAcquireSharedInterruptibly(arg);
}
// 尝试获得共享锁
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
// Sync 继承过来的方法, 方便阅读, 放在此处
// 以不公平的方式尝试获取共享锁
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();//剩下的资源数
int remaining = available - acquires; //分配完还剩多少资源
if (
// 如果资源已经用完, 返回负数, 表示获取失败, 进入 doAcquireSharedInterruptibly
remaining < 0 ||
// 如果资源足够,cas重试成功, 返回正数, 表示获取成功
compareAndSetState(available, remaining)
) {
return remaining;
}
}
}
// AQS 继承过来的方法, 方便阅读, 放在此处
// 资源不够,进入AQS队列
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) {
// 成功后本线程出队(AQS), 所在 Node设置为 head
// 如果 head.waitStatus == Node.SIGNAL ==> 0 成功, 下一个节点 unpark
// 如果 head.waitStatus == 0 ==> Node.PROPAGATE
// r 表示可用资源数, 为 0 则不会继续传播
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
// 不成功, 设置上一个节点 waitStatus = Node.SIGNAL, 下轮进入 park 阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
}
} finally {
if (failed)
cancelAcquire(node);
}
}
// Semaphore 方法, 方便阅读, 放在此处
// 默认一次释放一个资源
public void release() {
sync.releaseShared(1);
}
// AQS 继承过来的方法, 方便阅读, 放在此处
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
//如果释放资源成功,则让AQS中的node获取资源
doReleaseShared();
return true;
}
return false;
}
// Sync 继承过来的方法, 方便阅读, 放在此处
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();//现在有多少资源
int next = current + releases;//释放之后有多少资源
if (next < current) // releases < 0
throw new Error("Maximum permit count exceeded");
//以cas的方式把state与current比较后设置为next,即释放后的资源
if (compareAndSetState(current, next))
return true;
}
}
//在tryReleaseShared成功后,让AQS中的node获取资源
private void doReleaseShared() {
//死循环,只有发现h没有变化时才会退出
//h一定会变化是因为获取了资源
for (;;) {
Node h = head;
//判断是否至少有两个node,才能至少有一个可以获取资源的node
//0个说明head=tail=null,还没初始化
//1个说明已经初始化了dummy
if (h != null && h != tail) {
int ws = h.waitStatus;
//如果状态为signal,说明h的后继是需要通知的
//只要h成功的从signal修改为0,那么后续节点也会被唤醒
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;
}
//如果状态为PROPAGATE,直接判断head是否变化
if (h == head)
break;
}
}
}