1.Semaphore类注释摘抄
将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多 Lock
实现不同),即可以由线程(其他线程)释放“锁”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。
2.Sync实现了AQS类
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
//初始化时,根据初始化许可数量设置AQS的state
Sync(int permits) {
setState(permits);
}
final int getPermits() {
return getState();
}
//共享状态下的非公平获取锁
final int nonfairTryAcquireShared(int acquires) {
for (;;) {//在死循环中,先获取state,如果试图获取的锁数量减掉之后,还大于0,则设置state
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
}
//减少许可证数量
final void reducePermits(int reductions) {
for (;;) {
int current = getState();
int next = current - reductions;
if (next > current) // underflow
throw new Error("Permit count underflow");
if (compareAndSetState(current, next))
return;
}
}
//将许可证减为0
final int drainPermits() {
for (;;) {
int current = getState();
if (current == 0 || compareAndSetState(current, 0))
return current;
}
}
}
3.非公平锁版本
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
//调用Sync中的非公平获取锁,在使用时,调用acquireShared()方法获取信号量,
//先尝试nonfairTryAcquireShared,如果state减去想获取的锁的数量>0,表示成功。直接返回
//如果获取失败,则将节点入队,然后等待锁,
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
4.公平锁版本
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (;;) {
//如果当前有等待锁的线程,则获取失败
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}