Semaphore
概述
Semaphore
来自于JDK 1.5
的JUC
包,直译过来就是信号量
,被作为一种多线程并发控制工具来使用Semaphore
可以控制同时访问共享资源的线程个数,线程通过acquire()
方法获取一个信号量,信号量减1
,如果没有就等待;通过release()
方法释放一个信号量,信号量加1
Semaphore
在API
是这么介绍的:一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire()
,然后再获取该许可。每个release()
添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore
只对可用许可的号码进行计数,并采取相应的行动
下面我们就一个停车场的简单例子来阐述 Semaphore
:
- 我们假设停车场仅有
5
个停车位,一开始停车场没有车辆所有车位全部空着,然后先后到来三辆车,停车场车位够,安排进去停车,然后又来三辆,这个时候由于只有两个停车位,所有只能停两辆,其余一辆必须在外面候着,直到停车场有空车位,当然以后每来一辆都需要在外面候着。当停车场有车开出去,里面有空位了,则安排一辆车进去(至于是哪辆要看选择的机制是公平还是非公平模式
) - 从程序角度看,停车场就相当于信号量
Semaphore
,其中许可数为5
,车辆就相对线程。当来一辆车时,许可数就会减1
,当停车场没有车位了(许可数= 0
),其他来的车辆需要在外面等候着。如果有一辆车开出停车场,许可数+1
,然后放进来一辆车
信号量 Semaphore
是一个非负整数(>= 1
)。
- 当一个线程想要访问某个共享资源时,它必须要先获取
Semaphore
,当Semaphore > 0
时,获取该资源并执行Semaphore 减 1
- 如果
Semaphore = 0
,则表示全部的共享资源已经被其他线程全部占用
,线程必须要等待其他线程释放资源 - 当其他线程释放资源时,执行
Semaphore + 1
操作
Semaphore
源码
类图
可以很明显的看出来 Semaphore
和 CountDownLatch
一样都是直接使用 AQS
实现的。区别就是 Semaphore
还分别实现了公平模式 FairSync
和非公平模式 NonfairSync
两个内部类
构造器及内部类
public class Semaphore implements java.io.Serializable {
private static final long serialVersionUID = -3222578661600680210L;
private final Sync sync;
/*创建具有给定的信号量数和非公平模式的 Semaphore*/
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
/*创建具有给定的信号量数和给定的公平设置的 Semaphore*/
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
/*非公平模式的实现*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
//......
}
/*公平模式的实现*/
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
//......
}
/*信号量的同步实现。 使用 AQS 的state状态表示信号量。子分类为公平和非公平模式*/
abstract static class Sync extends</