Semaphore
1. 前言
- Semaphore是一个计数信号量,它的本质是一个共享锁。
- 线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
- Semaphore包含Sync对象,有公平信号量和非公平信号量之分
2. 源码解析
2.1 数据结构
同ReentrantLock一样,Semaphore包含Sync对象,有公平信号量和非公平信号量之分,默认非公平信号量
2.2 内部类
- FairSync
1 | static final class FairSync extends Sync { |
- NonfairSync
1 | static final class NonfairSync extends Sync { |
nonfairTryAcquireShared 在Sync中定义:
1 | final int nonfairTryAcquireShared(int acquires) { |
公平信号量和非公平信号量的获取信号量机制不同:对于公平信号量而言,如果当前线程不在CLH队列的头部,则排队等候;而对于非公平信号量而言,无论当前线程是不是在CLH队列的头部,它都会直接获取信号量。
而释放信号量的机制是相同的。
2.3 核心方法
- Semaphore()构造方法
1 | public Semaphore(int permits) { |
是通过Sync来设置锁计数
1 | Sync(int permits) { |
- acquire()信号量获取
1 | // 从信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。 |
实际上是调用的AQS中的acquireSharedInterruptibly()。
1 | public final void acquireSharedInterruptibly(int arg) |
doAcquireSharedInterruptibly()使当前线程等待,直到获取共享锁或被中断才返回
1 | private void doAcquireSharedInterruptibly(long arg) |
- release()信号量释放
1 | public void release(int permits) { |
releaseShared()方法在AQS中定义
1 | public final boolean releaseShared(int arg) { |
tryReleaseShared()在Sync中定义,公平信号量和非公平信号量机制相同
1 | protected final boolean tryReleaseShared(int releases) { |
doReleaseShared()释放共享锁。它会从前往后的遍历CLH队列,依次“唤醒”然后“执行”队列中每个节点对应的线程;最终的目的是让这些线程释放它们所持有的信号量。
1 | private void doReleaseShared() { |