一、前言

  分析了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总共有三个内部类,并且三个内部类是紧密相关的,下面先看三个类的关系。

【JUC】JDK1.8源码分析之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;
            }
        }
    }
View Code

相关文章: