Semaphore
概述
Semaphore
来自于JDK 1.5
的JUC
包,直译过来就是信号量
,被作为一种多线程并发控制工具来使用Semaphore
可以控制同时访问共享资源的线程个数,线程通过acquire()
方法获取一个信号量,信号量减一,如果没有就等待;通过release()
方法释放一个信号量,信号量加一- 它通过控制信号量的总数量,以及每个线程所需获取的信号量数量,进而控制多个线程对共享资源访问的并发度,以保证合理的使用共享资源。相比
synchronized
和独占锁一次只能允许一个线程访问共享资源,功能更加强大,有点类似于共享锁
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 AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
Sync(int permits) {
//被设置为state值
setState(permits);
}
//......
}
}
- 实际上公平与非公平只是在获取信号量的时候得到体现,它们的释放信号量的方法都是一样的,这就类似于
ReentrantLock
:公平与非公平只是在获取锁的时候得到体现,它们的释放锁的方法都是一样的 - 在构造器部分,如同
CountDownLatch
构造函数传递的初始化计数个数count
被赋给了AQS
的state
状态变量一样,Semaphore
的信号量个数permits
同样赋给了AQS
的state
值 - 在创建
Semaphore
时可以使用一个fair
变量指定是否使用公平策略,默认是非公平模式
。公平模式会确保所有等待的获取信号量的线程按照先进先出的顺序获取信号量,而非公平模式则没有这个保证。非公平模式的吞吐量比公平模式的吞吐量要高,而公平模式则可以避免线程饥饿