写在前面
作者_Doug Lea_如此描述这个类:A counting semaphore. Conceptually, a semaphore maintains a set of permits.
分析自JDK 1.8.0_171
顾名思义。计数信号量,它维护许可数量。acquire一个许可阻塞至池里有可用许可,release一个许可即往池里添加一个许可。
如下为源码中示例代码:
1 | class Pool { |
如上,示例中用到的api就两个,即acquire和release,意为获取一个许可及释放一个许可。
Sync变量
内部抽象类Sync继承自AQS,用AQS中的volatile int state变量表示许可数量。Sync的子类有两个版本,fair和nonfair。
1 | abstract static class Sync extends AbstractQueuedSynchronizer { |
Sync的两个子类,NonfairSync和FairSync,分别表示在获取许可时是非公平式(抢占式)和公平式。
Semaphore.acquire
获取许可,调用Sync.acquireSharedInterruptibly(1)。
1 | public final void acquireSharedInterruptibly(int arg) |
需要注意,当没有阻塞的节点时,即链表为空,这时往链表添加节点时是往一个”空”头节点后添加。唤醒时,在阻塞位置恢复再次循环,如果前驱是头结点且当前池中有许可,那么设置当前节点为头结点,并唤醒下一节点,否则再次阻塞。
Semaphore.release
调用Sync.releaseShared(1)。
1 | public final boolean releaseShared(int arg) { |
唤醒时总是唤醒头结点的下一节点。注意waitStatus这个状态,在阻塞时,会在shouldParkAfterFailedAcquire这个方法里,将当前阻塞节点的前缀设置为SIGNAL。