JUC代码浅析[4]——基于AQS的信号量Semaphore
Semaphore是基于AQS共享模式实现的计数信号量,它维护一个资源一个时期内最多访问者个数。超过限制数量的线程被阻塞。使用state表示许可的个数。acquire操作减少计数,release增加计数,许可计数为0时就不允许新的访问进入。
获取许可,
public void acquire() throws InterruptedException {
//acquireSharedInterruptibly方法参考AQS的介绍
sync.acquireSharedInterruptibly(1);
}
信号量sync也分为公平和非公平的实现,其中非公平sync,剩余许可小于0时线程就进入队列阻塞等待AQS调度
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available – acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
公平sync,只要当前线程不处于AQS队列的首位就进入队列阻塞等待调度,在首位时跟非公平一样
protected int tryAcquireShared(int acquires) {
Thread current = Thread.currentThread();
for (;;) {
Thread first = getFirstQueuedThread();
if (first != null && first != current)
return -1;
int available = getState();
int remaining = available – acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
释放许可,比较简单,增加许可
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int p = getState();
if (compareAndSetState(p, p + releases))
return true;
}
}