1. Semaphore基础概念与应用场景
信号量(Semaphore)是Java并发编程中一个经典的工具类,它最早由荷兰计算机科学家Dijkstra在1965年提出。在Java的JUC包中,Semaphore的实现完美体现了AQS框架的灵活性和扩展性。
1.1 Semaphore的核心作用
想象你正在管理一个共享单车停放点。这个停放点有50个停车位,当所有车位都被占用时,新来的用户必须等待直到有空位出现。Semaphore就是这样一个"停车位管理员",它维护着一组许可证(permits),每个线程在访问共享资源前必须先获取许可证,使用完毕后必须归还。
与ReentrantLock不同,Semaphore允许多个线程同时访问共享资源。这种特性使其特别适合以下场景:
- 资源池管理(数据库连接池、线程池)
- 流量控制(API限流)
- 生产者-消费者模式
- 并行任务控制
1.2 Semaphore的两种模式
Semaphore提供了公平和非公平两种工作模式:
java复制// 非公平模式(默认)
Semaphore nonFairSemaphore = new Semaphore(10);
// 公平模式
Semaphore fairSemaphore = new Semaphore(10, true);
公平模式遵循FIFO原则,保证等待时间最长的线程优先获取许可证;而非公平模式则允许"插队",虽然可能导致某些线程等待时间过长,但整体吞吐量更高。在实际应用中,非公平模式通常是更好的选择,除非有严格的公平性要求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. AQS框架与Semaphore实现原理
2.1 AQS共享模式解析
AbstractQueuedSynchronizer(AQS)是JUC包的核心基础框架,它通过一个FIFO队列和state变量实现了同步器的基本逻辑。AQS支持两种同步模式:
| 模式类型 | 特点 | 典型实现 |
|---|---|---|
| 独占模式 | 同一时刻只有一个线程能获取资源 | ReentrantLock |
| 共享模式 | 多个线程可以同时获取资源 | Semaphore, CountDownLatch |
Semaphore正是基于AQS的共享模式实现的。在构造Semaphore时指定的permits数量,实际上就是设置了AQS的state变量:
java复制// Semaphore.Sync的构造函数
Sync(int permits) {
setState(permits); // 将许可证数量存入AQS的state
}
2.2 关键数据结构
Semaphore的内部类结构清晰地展现了其实现原理:
java复制public class Semaphore implements java.io.Serializable {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
// 共享模式的核心实现
}
// 非公平版本
static final class NonfairSync extends Sync {
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
// 公平版本
static final class FairSync extends Sync {
protected int tryAcquireShared(int acquires) {
// 先检查是否有排队线程
}
}
}
这种设计体现了模板方法模式:Sync类实
