一、前言
分析了CountDownLatch源码后,下面接着分析Semaphore的源码。Semaphore称为计数信号量,它允许n个任务同时访问某个资源,可以将信号量看做是在向外分发使用资源的许可证,只有成功获取许可证,才能使用资源。下面开始分析Semaphore的源码。
二、Semaphore的数据结构
分析源码可以知道,Semaphore底层是基于AbstractQueuedSynchronizer来实现的,所以,Semaphore的数据结构也依托于AQS的数据结构,在前面对AQS的分析中已经指出了其数据结构,在这里不再累赘。
三、Semaphore源码分析
3.1 类的继承关系
public class Semaphore implements java.io.Serializable {}
说明:Semaphore实现了Serializable接口,即可以进行序列化。
3.2 类的内部类
Semaphore总共有三个内部类,并且三个内部类是紧密相关的,下面先看三个类的关系。
说明:Semaphore与ReentrantLock的内部类的结构相同,类内部总共存在Sync、NonfairSync、FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQueuedSynchronizer抽象类。下面逐个进行分析。
1. Sync类
Sync类的源码如下。
// 内部类,继承自AQS abstract static class Sync extends AbstractQueuedSynchronizer { // 版本号 private static final long serialVersionUID = 1192457210091910933L; // 构造函数 Sync(int permits) { // 设置状态数 setState(permits); } // 获取许可 final int getPermits() { return getState(); } // 共享模式下非公平策略获取 final int nonfairTryAcquireShared(int acquires) { for (;;) { // 无限循环 // 获取许可数 int available = getState(); // 剩余的许可 int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) // 许可小于0或者比较并且设置状态成功 return remaining; } } // 共享模式下进行释放 protected final boolean tryReleaseShared(int releases) { for (;;) { // 无限循环 // 获取许可 int current = getState(); // 可用的许可 int next = current + releases; if (next < current) // overflow throw new Error("Maximum permit count exceeded"); if (compareAndSetState(current, next)) // 比较并进行设置成功 return true; } } // 根据指定的缩减量减小可用许可的数目 final void reducePermits(int reductions) { for (;;) { // 无限循环 // 获取许可 int current = getState(); // 可用的许可 int next = current - reductions; if (next > current) // underflow throw new Error("Permit count underflow"); if (compareAndSetState(current, next)) // 比较并进行设置成功 return; } } // 获取并返回立即可用的所有许可 final int drainPermits() { for (;;) { // 无限循环 // 获取许可 int current = getState(); if (current == 0 || compareAndSetState(current, 0)) // 许可为0或者比较并设置成功 return current; } } }