整体概念
- 内部类Sync继承AQS,基于AQS实现锁的机制,通过state表示许可的数量
- 支持公平锁FairSync和非公平锁NonfairSync的模式
有关AQS的原理参考juejin.cn/post/748158… ,本文涉及AQS的方法不再重复分析
内部类介绍
Sync
//继承AQS
abstract static class Sync extends AbstractQueuedSynchronizer
构造方法
Sync(int permits) {
//设置state为许可值
setState(permits);
}
NonfairSync
非公平模式
//继承Sync实现非公平锁
static final class NonfairSync extends Sync
构造方法
NonfairSync(int permits) {
super(permits);
}
FairSync
公平模式
static final class FairSync extends Sync
构造方法
FairSync(int permits) {
super(permits);
}
构造方法
public Semaphore(int permits) {
//默认非公平模式
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
//支持模式调整,fair 为true公平模式,否则非公平模式
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
核心方法
acquire(int permits) 获取许可
public void acquire(int permits) throws InterruptedException {
//参数值校验
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
acquireSharedInterruptibly(int arg)
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (
//尝试获取许可资格,小于0失败
tryAcquireShared(arg) < 0)
//AQS中的方法不在分析
//加入同步队列等待再次获取资格
doAcquireSharedInterruptibly(arg);
}
tryAcquireShared(int acquires)
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
nonfairTryAcquireShared(int acquires)
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//许可数量
int available = getState();
//减1
int remaining = available - acquires;
if (
//小于0说明许可数量已经用完了
remaining < 0 ||
//否则尝试CAS设置
compareAndSetState(available, remaining))
//返回剩余许可数
return remaining;
}
}
release() 释放许可
public void release() {
sync.releaseShared(1);
}
releaseShared(int arg)
public final boolean releaseShared(int arg) {
if (
//尝试释放资格
tryReleaseShared(arg)) {
//AQS中的方法不在具体分析
//唤醒同步队列中没拿到许可资格的线程
doReleaseShared();
return true;
}
return false;
}
tryReleaseShared(int releases)
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//当前许可数量
int current = getState();
//归还数量
//归还一个在之前的数量上加1
int next = current + releases;
//校验
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (
//CAS
compareAndSetState(current, next))
return true;
}
}
Semaphore整体流程总结:
- Semaphore(int permits)构造许可数量,默认非公平模式;
- acquire(int permits)获取许可,成功则执行,失败加入同步队列阻塞;
- release()释放许可数量,循环执行直到成功释放,成功释放后唤醒同步队列节点,之前获取许可失败的也能继续执行了