当前位置: 首页 > article >正文

Java AQS Semaphore 源码

前言


 相关系列

  • 《Java & AQS & 目录》(持续更新)
  • 《Java & AQS & Semaphore & 源码》(学习过程/多有漏误/仅作参考/不再更新)
  • 《Java & AQS & Semaphore & 总结》(学习总结/最新最准/持续更新)
  • 《Java & AQS & Semaphore & 问题》(学习解答/持续更新)
     

 涉及内容

  • 《Java & AQS & 总结》
     
     

源码


/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package juc;

import juc.locks.AbstractQueuedSynchronizer;
import juc.locks.Lock;

import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * A counting semaphore.  Conceptually, a semaphore maintains a set of permits.  Each {@link #acquire} blocks if necessary
 * until a permit is available, and then takes it.  Each {@link #release} adds a permit, potentially releasing a blocking acquirer.
 * However, no actual permit objects are used; the {@code Semaphore} just keeps a count of the number available and acts
 * accordingly.
 * 计数信号量。从概念上讲,一个信号量维护一组许可。如果必要每个acquire方法都将阻塞直至许可变得可用并被获取。每个
 * release()方法新增一个许可,这可能释放一个阻塞中的获取。此外,没有实际许可对象可用,信号量只是保持数字总数相应地可
 * 用和活动(即许可只是单纯数字的增减)。
 * <p>
 * Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. For example,
 * here is a class that uses a semaphore to control access to a pool of items:
 * 信号量常常用于限制线程数量超过可访问的某些(物理的或逻辑的)资源。例如,这是一个使用信号量来控制访问一池项的类:
 * <pre> {@code
 * class Pool {
 *
 *   // 设置许可的数量并创建信号量。
 *   private static final int MAX_AVAILABLE = 100;
 *   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
 *
 *   public Object getItem() throws InterruptedException {
 *     // 获取(减少)许可,只有成功获取到许可才可以向下执行。
 *     available.acquire();
 *     return getNextAvailableItem();
 *   }
 *
 *   public void putItem(Object x) {
 *     // 将已使用结束的资源放回,并释放(增加)许可。
 *     if (markAsUnused(x))
 *       available.release();
 *   }
 *
 *   // Not a particularly efficient data structure; just for demo
 *   // 不是指定有效的数据结构,直至一个演示
 *   // whatever kinds of items being managed
 *   // 任意可被管理的资源。
 *
 *   // 创建资源及记录资源是否被获取的数据结构。
 *   protected Object[] items = ...
 *   protected boolean[] used = new boolean[MAX_AVAILABLE];
 *
 *   protected synchronized Object getNextAvailableItem() {
 *     // 获取资源数组中首个尚未被使用的资源,并记录其已被使用。
 *     for (int i = 0; i < MAX_AVAILABLE; ++i) {
 *       if (!used[i]) {
 *          used[i] = true;
 *          return items[i];
 *       }
 *     }
 *     // not reached
 *     // 未达到
 *     return null;
 *   }
 *
 *   protected synchronized boolean markAsUnused(Object item) {
 *     // 将已使用结束的资源放回资源数组,并撤销使用标志。
 *     for (int i = 0; i < MAX_AVAILABLE; ++i) {
 *       if (item == items[i]) {
 *          if (used[i]) {
 *            used[i] = false;
 *            return true;
 *          } else
 *            return false;
 *       }
 *     }
 *     return false;
 *   }
 * }}</pre>
 *
 * <p>
 * Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an item is available for
 * use. When the thread has finished with the item it is returned back to the pool and a permit is returned to the semaphore,
 * allowing another thread to acquire that item.  Note that no synchronization lock is held when {@link #acquire} is called as
 * that would prevent an item from being returned to the pool.  The semaphore encapsulates the synchronization needed to
 * restrict access to the pool, separately from any synchronization needed to maintain the consistency of the pool itself.
 * 获取一个项前每个线程必须从信号量中获取/减少一个许可,以保证项可正常使用。当项已被线程使用结束则将至回归池并返回
 * 一个许可至信号量,以允许其它线程获取项。注意:当acquire()方法被调用没有同步锁被持有,因为这会阻止项返回池中。信号
 * 量封装了限制访问池所需的同步,将之与维护池自身一致性的同步分离。
 * <p>
 * A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual
 * exclusion lock.  This is more commonly known as a <em>binary semaphore</em>, because it only has two states: one permit
 * available, or zero permits available.  When used in this way, the binary semaphore has the property (unlike many {@link Lock}
 * implementations), that the &quot;lock&quot; can be released by a thread other than the owner (as semaphores have no
 * notion of ownership).  This can be useful in some specialized contexts, such as deadlock recovery.
 * 信号量初始化为1,此时它只有最多一个许可可用,可作为多重排它锁。这更常规被称为二进制信号量,因为它只有两个状态:
 * 一个许可可用或无许可可用。当通过这种方式使用时,二进制信号量具有锁的特性(不像一些锁实现),可以通过非拥有者的线
 * 程释放(即信号量没有所有权的概念)。这在某些指定环境中可能很有用,比如死锁恢复。
 * <p>
 * The constructor for this class optionally accepts a <em>fairness</em> parameter. When set false, this class makes no
 * guarantees about the order in which threads acquire permits. In particular, <em>barging</em> is permitted, that is, a
 * thread invoking {@link #acquire} can be allocated a permit ahead of a thread that has been waiting - logically the new
 * thread places itself at the head of the queue of waiting threads. When fairness is set true, the semaphore guarantees that
 * threads invoking any of the {@link #acquire() acquire} methods are selected to obtain permits in the order in which their
 * invocation of those methods was processed (first-in-first-out; FIFO). Note that FIFO ordering necessarily applies to specific
 * internal points of execution within these methods.  So, it is possible for one thread to invoke {@code acquire} before
 * another, but reach the ordering point after the other, and similarly upon return from the method. Also note that the untimed
 * {@link #tryAcquire() tryAcquire} methods do not honor the fairness setting, but will take any permits that are available.
 * 该类的构造器可选择性地接受一个公平性参数。当设置为false时,该类不保证此时线程获取许可的顺序。尤其是碰撞被允许,
 * 一个线程调用acquire()方法会先于等待中的线程分配许可 —— 逻辑上新线程会将自己置于等待线程队列的前方。当公平性被
 * 设置为true,信号量保证调用acquire方法的线程被选择以按照它们调用这些方法的顺序获得许可。注意:先入先出顺序必须应
 * 用于这些方法中的指定内部执行点。所以,一个线程在其它线程之前调用acquire()方法,但却在其它线程之后到达命令点是可
 * 能的,这与从方法返回之后(调用)相似。还要注意的是:非定时tryAcquire()方法不尊重公平性设置(即不受影响),将获取
 * 任意可用的许可。
 * <p>
 * Generally, semaphores used to control resource access should be initialized as fair, to ensure that no thread is starved
 * out from accessing a resource. When using semaphores for other kinds of synchronization control, the throughput advantages
 * of non-fair ordering often outweigh fairness considerations.
 * 通常,信号量被用于控制资源方式应该初始化为公平,以确定没有线程在访问资源时饥饿。当为了其他类型的同步控制使用信号
 * 量时,非公平顺序的吞吐量优势往往超过公平性考虑。
 * <p>
 * This class also provides convenience methods to {@link #acquire(int) acquire} and {@link #release(int) release} multiple
 * permits at a time.  Beware of the increased risk of indefinite postponement when these methods are used without fairness
 * set true.
 * 该类还提供用于同时获取及释放多重许可的便利方法。当有些方法不公平使用时注意无限期延迟的风险增加。
 * <p>
 * Memory consistency effects: Actions in a thread prior to calling a "release" method such as {@code release()}
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> actions following a successful "acquire" method
 * such as {@code acquire()} in another thread.
 * 内存一致性影响:线程中优先于释放系方法的活动先行发生于另一个线程中成功的获取系方法的活动。
 *
 * @author Doug Lea
 * @Description: 信号量
 * @since 1.5
 */
public class Semaphore implements java.io.Serializable {

    private static final long serialVersionUID = -3222578661600680210L;

    /**
     * All mechanics via AbstractQueuedSynchronizer subclass
     * 通过AQS子类实现所有机制
     *
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 同步
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: 持有当前信号量的同步,同步是AQS的子类对象,用于实现信号量的功能
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    private final Sync sync;

    /**
     * Synchronization implementation for semaphore.  Uses AQS state to represent permits. Subclassed into fair and nonfair
     * versions.
     * 关于信号量的同步实现。使用AQS状态表示许可。子类分为公平和不公平版本
     *
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * @Description: 同步类
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * @Description: AQS的子类,用于实现信号量类的公共模式
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * @Description: ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * @Description: ~
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {

        private static final long serialVersionUID = 1192457210091910933L;

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * @Description: 同步
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 创建指定许可数量的同步
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * @Description: 方法会将指定直接存入父类AQS的[状态]中。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * @Description: ~
         */
        Sync(int permits) {
            // 将预定的共享许可数量设置进AQS的state中。
            setState(permits);
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * @Description: 获取许可
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * @Description: 获取当前同步的许可
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * @Description: 方法直接将AQS的[状态]返回实现。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * @Description: ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * @Description: ~
         */
        final int getPermits() {
            return getState();
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 不公平尝试获取分享
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 获取当前信号量指定数量的许可,并返回剩余可用许可的数量。当返回的剩余可用许可数量为负数时表示此次获取由于
         * 剩余可用许可数量而失败。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 法首先会获取可用[状态/许可],随后将可用[状态/许可]减去指定许可数量得到剩余许可。如果剩余许可小于0或者CAS
         * 将[状态/许可]修改为剩余许可成功则将方法返回,因为这意味着当前信号量已无足够的可用许可或已获取许可成功;否
         * 则说明CAS修改[状态/许可]操作失败,需要继续循环上述流程直至返回为止。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        final int nonfairTryAcquireShared(int acquires) {
            // 方法首先会获取可用[状态/许可],随后将可用[状态/许可]减去指定许可数量得到剩余许可。如果剩余许可小于0或
            // 者CAS将[状态/许可]修改为剩余许可成功则将方法返回,因为这意味着当前信号量已无足够的可用许可或已获取许
            // 可成功;否则说明CAS修改[状态/许可]操作失败,需要继续循环上述流程直至返回为止。
            for (; ; ) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 || compareAndSetState(available, remaining)) {
                    return remaining;
                }
            }
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 尝试释放共享
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 释放当前信号量指定数量的许可,并返回true表示释放成功。该方法不会返回false,但如果释放导致许可总数溢出将抛
         * 出错误。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法首先会获取[状态/许可],随后将之于指定许可数量相加得到释放后可用许可数量。如果释放后可用许可数量小于[
         * 状态/许可],说明发生了溢出(也可能是传入的指定许可数量不合法),直接抛出错误;否则通过CAS操作将释放后可
         * 用许可数量赋予[状态/许可]。由于CAS操作可能失败,因此需要不断循环上述操作直至成功并返回true。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        @Override
        protected final boolean tryReleaseShared(int releases) {
            // 方法首先会获取[状态/许可],随后将之于指定许可数量相加得到释放后可用许可数量。如果释放后可用许可数量小
            // 于[状态/许可],说明发生了溢出(也可能是传入的指定许可数量不合法),直接抛出错误;否则通过CAS操作将释
            // 放后可用许可数量赋予[状态/许可]。由于CAS操作可能失败,因此需要不断循环上述操作直至成功并返回true。
            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;
                }
            }
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 减少许可
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 减少当前信号量指定数量的许可。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法首先会获取[状态/许可],随后将之于指定许可数量相减得到减少后可用许可数量。如果减少后可用许可数量大于[
         * 状态/许可],说明发生了下溢出(也可能是传入的指定许可数量不合法),直接抛出错误;否则通过CAS操作将减少后
         * 可用许可数量赋予[状态/许可]。由于CAS操作可能失败,因此需要不断循环上述操作直至成功并返回true。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        final void reducePermits(int reductions) {
            // 方法首先会获取[状态/许可],随后将之于指定许可数量相减得到减少后可用许可数量。如果减少后可用许可数量大
            // 于[状态/许可],说明发生了下溢出(也可能是传入的指定许可数量不合法),直接抛出错误;否则通过CAS操作将
            // 减少后可用许可数量赋予[状态/许可]。由于CAS操作可能失败,因此需要不断循环上述操作直至成功并返回true。
            for (; ; ) {
                int current = getState();
                int next = current - reductions;
                if (next > current) {
                    // underflow
                    throw new Error("Permit count underflow");
                }
                if (compareAndSetState(current, next)) {
                    return;
                }
            }
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 流失许可
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 流失当前信号量的所有许可。
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法首先会获取[状态/许可],随后判断其是否为0或者CAS修改[状态/许可]为0是否成功,是则返回[状态/许可]表示成
         * 功流失的许可总数;否则循环上述操作直至成功为止。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        final int drainPermits() {
            // 方法首先会获取[状态/许可],随后判断其是否为0或者CAS修改[状态/许可]为0是否成功,是则返回[状态/许可]表示
            // 成功流失的许可总数;否则循环上述操作直至成功为止。
            for (; ; ) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0)) {
                    return current;
                }
            }
        }
    }

    /**
     * NonFair version
     * 不公平版本
     */
    static final class NonfairSync extends Sync {

        private static final long serialVersionUID = -2694183684443567898L;

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 创建指定许可数量的不公平同步
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法直接通过父类同步类的构造方法将指定许可数量存入AQS的[状态]。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        NonfairSync(int permits) {
            // 设置许可数量。
            super(permits);
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 尝试获取共享
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 获取当前不公平同步指定数量的许可
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法直接通过父类的nonfairTryAcquireShared(int acquires)方法实现。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        @Override
        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }

    }

    static final class FairSync extends Sync {

        private static final long serialVersionUID = 2014338818796000944L;

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 创建指定许可数量的公平同步
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法直接通过父类同步类的构造方法将指定许可数量存入AQS的[状态]。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * ~
         */
        FairSync(int permits) {
            // 设置许可。
            super(permits);
        }

        /**
         * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
         * 尝试获取共享
         * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
         * 获取当前不公平同步指定数量的许可
         * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
         * 方法首先会判断AQS的同步队列中是否已存在正在获取许可的线程,存在则直接返回-1,因为公平同步必须按顺序获取
         * 许可,在已存在正在获取许可线程的情况下当前线程是必然无法获取到许可的,故而直接返回-1表示获取失败。
         * 在没有正在获取许可线程的情况下,方法会获取[状态/许可],并将之与指定数量相减以获取的剩余可用许可数量。如果
         * 剩余可用许可数量小于0或者CAS修改[状态/许可]为剩余可用许可数量成功小于0则直接返回剩余可用许可数量表示成功,
         * 否则继续循环上述流程直至成功为止。
         * @Description: ----------------------------------------------------------- 注意 -----------------------------------------------------------
         * ~
         * @Description: ----------------------------------------------------------- 疑问 -----------------------------------------------------------
         * TODO 信号量类支持获取指定数量的许可,因为同步队列中的线程可能是因为剩余可用许可数量不足而存在,而非为0
         * TODO 而存在,所以为什么当同步队列中存在线程时就直接返回呢?
         */
        @Override
        protected int tryAcquireShared(int acquires) {
            for (; ; ) {
                // 方法首先会判断AQS的同步队列中是否已存在正在获取许可的线程,存在则直接返回-1,因为公平同步必须按顺
                // 序获取许可,在已存在正在获取许可线程的情况下当前线程是必然无法获取到许可的,故而直接返回-1表示获取
                // 失败。
                if (hasQueuedPredecessors()) {
                    return -1;
                }
                // 在没有正在获取许可线程的情况下,方法会获取[状态/许可],并将之与指定数量相减以获取的剩余可用许可数量。
                // 如果剩余可用许可数量小于0或者CAS修改[状态/许可]为剩余可用许可数量成功小于0则直接返回剩余可用数量许
                // 可表示成功,否则继续循环上述流程直至成功为止。
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 || compareAndSetState(available, remaining)) {
                    return remaining;
                }
            }
        }

    }

    /**
     * Creates a {@code Semaphore} with the given number of permits and nonfair fairness setting.
     * 随着指定许可数量和非公平设置创建信号量
     *
     * @param permits the initial number of permits available. This value may be negative, in which case releases must occur
     *                before any acquires will be granted.
     *                许可可用的初始数量。该值可能为负数,这种情况下释放必须发生在任意获取被允许之前。
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 创建指定许可数量的非公平信号量
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法通过直接创建一个非公平[同步]实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public Semaphore(int permits) {
        // 默认使用的是非公平同步机制。
        sync = new NonfairSync(permits);
    }

    /**
     * Creates a {@code Semaphore} with the given number of permits and the given fairness setting.
     * 随着指定许可数量及指定公平性设置创建信号量。
     *
     * @param permits the initial number of permits available. This value may be negative, in which case releases must occur
     *                before any acquires will be granted.
     *                许可可用的初始数量。该值可能为负数,这种情况下释放必须发生在任意获取被允许之前。
     * @param fair    {@code true} if this semaphore will guarantee first-in first-out granting of permits under contention,
     *                else {@code false}
     *                如果当前信号量在竞争下将保证FIFO的许可批准则为true;否则false。
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 创建指定许可数量及公平性的信号量
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法通过直接创建一个非公平[同步]实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

    /**
     * Acquires a permit from this semaphore, blocking until one is available, or the thread is
     * {@linkplain Thread#interrupt interrupted}.
     * 从信号量中获取许可,阻塞直至一个许可变得可用,或者线程被中断。
     * <p>
     * Acquires a permit, if one is available and returns immediately, reducing the number of available permits by one.
     * 获取许可,如果一个可用则立即返回,并减少一个可用许可。
     * <p>
     * If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant
     * until one of two things happens:
     * 如果没有许可可用则当前线程为了线程计划目的变得无效并且休眠直至两种情况之一发生:
     * <ul>
     * <li>Some other thread invokes the {@link #release} method for this semaphore and the current thread is next to be
     * assigned a permit; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread.
     * </ul>
     * 某些其它线程调用当前信号量的release()方法并且当前线程是下个获取许可的线程;或者某些其它线程中断当前线程。
     * <p>
     * If the current thread:
     * 如果当前线程:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting for a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's interrupted status is cleared.
     * 在进入当前方式时(前)被设置为中断状态;或者在等待一个许可期间被中断,那么将抛出中断异常并且当前线程的中断
     * 状态将被清除。
     *
     * @throws InterruptedException if the current thread is interrupted
     *                              中断异常:如果当前线程被中断
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取一个许可,如果没有许可则当前线程会等待至存在一个许可为止。而如果当前线程在进入方法前/时及
     * 等待中被中断则将抛出中断异常。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的acquireSharedInterruptibly(int arg)方法实现,其底层逻辑是尝试获取许可,获取成功则返回,否则
     * 将当前线程纳入同步队列中封装为共享节点等待。而如果当前线程在计入方法前/时及等待中被中断则将抛出中断异常。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     * Acquires a permit from this semaphore, blocking until one is available.
     * 从当前信号量中获取一个许可,阻塞至一个许可可用。
     * <p>
     * Acquires a permit, if one is available and returns immediately, reducing the number of available permits by one.
     * 获取许可,如果一个可用则立即返回,并减少一个可用许可。
     * <p>
     * If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant
     * until some other thread invokes the {@link #release} method for this semaphore and the current thread is next to be
     * assigned a permit.
     * 如果没有许可可用则当前线程将为了线程计划目的变得无效并休眠直至其它线程调用当前信号量的release()方法并且线程
     * 是下个获取许可的线程。
     * <p>
     * If the current thread is {@linkplain Thread#interrupt interrupted} while waiting for a permit then it will continue to
     * wait, but the time at which the thread is assigned a permit may change compared to the time it would have received
     * the permit had no interruption occurred.  When the thread does return from this method its interrupt status will be set.
     * 如果当前线程在等待许可期间被中断那么它将继续等待,但是线程已分配许可的时间与线程没有中断时接收许可的时间相
     * 比可能发生改变(即线程因为被中断唤醒而恰好获得许可而非被指定信号唤醒而获得许可)。当线程从当前方法中返回时
     * 其中断状态将被设置(如果被中断的话)。
     *
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取(不中断)
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取一个许可,如果没有许可则当前线程会等待至存在一个许可为止。而如果当前线程在进入方法前/时及
     * 等待中被中断并不会抛出中断异常,但线程的中断状态会被保留。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的acquireShared(int arg)方法实现,其底层逻辑是尝试获取许可,获取成功则返回,否则将当前线程
     * 纳入同步队列中封装为共享节点等待。而如果当前线程在进入方法前/时及等待中被中断并不会抛出中断异常,但线程的
     * 中断状态会被保留。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void acquireUninterruptibly() {
        // 相当于不中断的获取。
        sync.acquireShared(1);
    }

    /**
     * Acquires a permit from this semaphore, only if one is available at the time of invocation.
     * 只有当调用时间时有许可可用是从当前信号量中获取一个许可。
     * <p>
     * Acquires a permit, if one is available and returns immediately, with the value {@code true}, reducing the number of
     * available permits by one.
     * 获取一个许可,如果一个许可可用则随着true立即返回,并减少一个可用许可。
     * <p>
     * If no permit is available then this method will return immediately with the value {@code false}.
     * 如果没有许可可用则当前方法将理解返回false。
     * <p>
     * Even when this semaphore has been set to use a fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
     * immediately acquire a permit if one is available, whether or not other threads are currently waiting. This
     * &quot;barging&quot; behavior can be useful in certain circumstances, even though it breaks fairness. If you want to
     * honor the fairness setting, then use {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) } which is
     * almost equivalent (it also detects interruption).
     * 即使当当前信号量被设置使用公平顺序策略,tryAcquire()的调用如果有许可可用也会立即返回,无论其它线程是否正在等
     * 待。该冲撞行为在某些情况中很有用,即使它破坏公平。如果你希望去
     *
     * @return {@code true} if a permit was acquired and {@code false} otherwise
     * 如果获取许可则返回true;否则返回false;
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 尝试获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取一个许可,如果存在可用许可则返回true;否则直接返回false。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的nonfairTryAcquireShared(int arg)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public boolean tryAcquire() {
        return sync.nonfairTryAcquireShared(1) >= 0;
    }

    /**
     * Acquires a permit from this semaphore, if one becomes available within the given waiting time and the current thread
     * has not been {@linkplain Thread#interrupt interrupted}.
     * 如果在指定等待时间内有一个许可变得可用且当前线程没有被中断则从信号量中获取一个许可。
     * <p>
     * Acquires a permit, if one is available and returns immediately, with the value {@code true}, reducing the number of
     * available permits by one.
     * 获取一个许可,如果一个许可可用则随着true立即返回,并减少一个可用许可。
     * <p>
     * If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant until
     * one of three things happens:
     * 如果没有许可可用则当前线程会为了线程计划目的变得无效并休眠直至三种情况中的一种发生:
     * <ul>
     * <li>Some other thread invokes the {@link #release} method for this semaphore and the current thread is next to be
     * assigned a permit; or Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or The specified
     * waiting time elapses.
     * 某些线程调用当前信号量的release()方法并且当前线程已被指定许可;或者其它线程中断当前线程中;或者指定等待时间消
     * 逝。
     * <p>
     * If a permit is acquired then the value {@code true} is returned.
     * 如果许可许可被获取则返回true。
     * <p>
     * If the current thread:
     * 如果当前线程:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting to acquire a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's interrupted status is cleared.
     * 在进入当前线程前被设置中断状态;或者在等待获取许可期间被中断,那么将抛出中断异常并且当前线程的中断状态将被
     * 清理。
     * <p>
     * If the specified waiting time elapses then the value {@code false} is returned.  If the time is less than or equal to
     * zero, the method will not wait at all.
     * 如果指定等待时间消逝那么将返回false。如果时间小于等于0则方法将不会等待。
     *
     * @param timeout the maximum time to wait for a permit 等待许可的最大时间
     * @param unit    the time unit of the {@code timeout} argument 超时参数的时间单位
     * @return {@code true} if a permit was acquired and {@code false} if the waiting time elapsed before a permit was
     * acquired
     * 如果许可被获取则返回true;如果在获取许可前等待时间消逝则返回false
     * @throws InterruptedException if the current thread is interrupted
     *                              中断异常:如果当前线程被中断
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 尝试获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取一个许可,如果存在可用许可则返回true;否则在指定等待时间内等待至存在可用许可为止。超时则
     * 返回false。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的tryAcquireSharedNanos(int arg, long nanosTimeout) 方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
        // 在一定的时间内尝试获取(可中断),失败会入队。
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /**
     * Releases a permit, returning it to the semaphore.
     * 释放许可,将之放回信号量。
     * <p>
     * Releases a permit, increasing the number of available permits by one. If any threads are trying to acquire a permit,
     * then one is selected and given the permit that was just released.  That thread is (re)enabled for thread scheduling
     * purposes.
     * 释放许可,递增一个可用许可。如果任意线程尝试获取许可,则刚被释放的许可将被选中。线程为了线程调度目的将重新
     * 可用。
     * <p>
     * There is no requirement that a thread that releases a permit must have acquired that permit by calling {@link #acquire}.
     * Correct usage of a semaphore is established by programming convention in the application.
     * 释放许可的线程并没有要求必须有通过调用acquire()方法获取的许可。一个信号量正确的用法是通过程序程序中的编程协
     * 定来确定的。
     *
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 释放
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 为当前信号量释放许可,其本质是增加一个可用许可,即方法不要求释放许可的线程必须获取过许可。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的releaseShared(int arg)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void release() {
        // 死循环式的释放许可,以保证释放一定成功,并对同步队列中的节点进行唤醒。
        sync.releaseShared(1);
    }

    /**
     * Acquires the given number of permits from this semaphore, blocking until all are available, or the thread is
     * {@linkplain Thread#interrupt interrupted}.
     * 从当前信号量中获取指定数量的许可,阻塞直至指定数量的许可可用,或者线程被中断。
     * <p>
     * Acquires the given number of permits, if they are available, and returns immediately, reducing the number of available
     * permits by the given amount.
     * 获取指定数量的许可,如果都可用则理解返回,并减少指定总数的可用许可。
     * <p>
     * If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes and lies
     * dormant until one of two things happens:
     * 如果不充分的许可可用那么线程将处于线程调度目的变得不可用并休眠直至两种情况的其中一种发生:
     * <ul>
     * <li>Some other thread invokes one of the {@link #release() release} methods for this semaphore, the current thread is
     * next to be assigned permits and the number of available permits satisfies this request; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread.
     * </ul>
     * 某些其它线程调用当前信号量的release()方法,当前线程被下个分配许可并且可用许可的数量满足请求;或者某些线程中
     * 断当前线程。
     * <p>
     * If the current thread:
     * 如果当前线程:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting for a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's interrupted status is cleared. Any permits that
     * were to be assigned to this thread are instead assigned to other threads trying to acquire permits, as if permits had
     * been made available by a call to {@link #release()}.
     * 在进入当前方法时被设置中断状态或者在等待许可期间被中断那么会抛出中断异常并且当前线程的中断状态会被清除。任意
     * 被分配给当前线程的许可将被转而分配给其它尝试获取许可的线程,通过调用release()方法许可将变得可用。
     *
     * @param permits the number of permits to acquire 用于获取的许可数量
     * @throws InterruptedException     if the current thread is interrupted
     *                                  中断异常:如果当前线程被中断
     * @throws IllegalArgumentException if {@code permits} is negative
     *                                  非法参数异常:如果许可为负数
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取指定数量的许可,其本质是减少许可的数量。如果没有足够的可用许可则当前线程会等待至存在指定
     * 数量的可用许可为止。而如果当前线程在进入方法前/时及等待中被中断则将抛出中断异常。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可是否合法,不合法则抛出非法参数异常;否则直接通过[同步]的
     * acquireSharedInterruptibly(int arg)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void acquire(int permits) throws InterruptedException {
        if (permits < 0) {
            throw new IllegalArgumentException();
        }
        sync.acquireSharedInterruptibly(permits);
    }

    /**
     * Acquires the given number of permits from this semaphore, blocking until all are available.
     * 从当前信号量中获取指定数量的许可,阻塞直至指定数量的许可可用。
     * <p>
     * Acquires the given number of permits, if they are available, and returns immediately, reducing the number of available
     * permits by the given amount.
     * 获取指定数量的许可,如果指定数量的许可可用则理解返回,并减少指定数量的可用许可数量。
     * <p>
     * If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes and lies
     * dormant until some other thread invokes one of the {@link #release() release} methods for this semaphore, the current
     * thread is next to be assigned permits and the number of available permits satisfies this request.
     * 如果可用的许可数量不充足那么当前线程处于线程调度的目的将变得不可用并休眠至其它线程调用当前信号量的release()方
     * 法,当前线程被下个用于分配许可并且可用许可数量满足于请求。
     * <p>
     * If the current thread is {@linkplain Thread#interrupt interrupted} while waiting for permits then it will continue to
     * wait and its position in the queue is not affected.  When the thread does return from this method its interrupt status
     * will be set.
     * 如果当前线程在等待许可期间被中断那么它将继续等待并且它在队列中的位置不会受到影响。当线程从该方法中返回时它
     * 的中断状态将被保留。
     *
     * @param permits the number of permits to acquire 用户获取的许可数量
     * @throws IllegalArgumentException if {@code permits} is negative
     *                                  非法参数异常:如果许可为负数
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取(不中断)
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取指定数量的许可,其本质是减少许可的数量。如果没有足够的可用许可则当前线程会等待至存在指定
     * 数量的可用许可为止。而如果当前线程在进入方法前/时及等待中被中断并不会抛出中断异常,但线程的中断状态会被保留。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可是否合法,不合法则抛出非法参数异常;否则直接通过[同步]的acquireShared(int arg)方法
     * 实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void acquireUninterruptibly(int permits) {
        // 许可的数量需要合法。
        if (permits < 0) {
            throw new IllegalArgumentException();
        }
        sync.acquireShared(permits);
    }

    /**
     * Acquires the given number of permits from this semaphore, only if all are available at the time of invocation.
     * 只当调用时存在指定数量的可用许可时从当前信号量中获取指定数量的许可。
     * <p>
     * Acquires the given number of permits, if they are available, and returns immediately, with the value {@code true},
     * reducing the number of available permits by the given amount.
     * 获取指定数量的许可,如果指定数量的许可可用则随着true立即返回;并减少指定数量的许可。
     * <p>
     * If insufficient permits are available then this method will return immediately with the value {@code false} and the
     * number of available permits is unchanged.
     * 如果可用许可数量不足则当前方法将随着false立即返回并且可用许可的数量不会改变。
     * <p>
     * Even when this semaphore has been set to use a fair ordering policy, a call to {@code tryAcquire} <em>will</em>
     * immediately acquire a permit if one is available, whether or not other threads are currently waiting. This
     * &quot;barging&quot; behavior can be useful in certain circumstances, even though it breaks fairness. If you want to
     * honor the fairness setting, then use {@link #tryAcquire(int, long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) }
     * which is almost equivalent (it also detects interruption).
     * 即使当前信号量被设置为公平顺序策略,如果指定数量的许可可用则tryAcquire()方法调用也将立即获取指定数量的许可,
     * 无论其它线程是否正在等待。该冲撞行为在某些情况下很有用,即使它破坏公平性。如果你想要遵守公平性设置,那使用
     * tryAcquire(int, long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS)方法技术是等效的(它还检查中断)。
     *
     * @param permits the number of permits to acquire 用于获取的许可数量
     * @return {@code true} if the permits were acquired and {@code false} otherwise
     * 如果获取到许可则返回true;否则返回false。
     * @throws IllegalArgumentException if {@code permits} is negative
     *                                  非法参数异常:如果许可为负
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 尝试获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取指定数量的许可,其本质是减少许可的数量。如果没有足够的可用许可则直接返回false;否则直接返
     * 回true。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可是否合法,不合法则抛出非法参数异常;否则直接通过[同步]的
     * nonfairTryAcquireShared(int arg)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public boolean tryAcquire(int permits) {
        // 许可的数量需要合法。
        if (permits < 0) {
            throw new IllegalArgumentException();
        }
        return sync.nonfairTryAcquireShared(permits) >= 0;
    }

    /**
     * Acquires the given number of permits from this semaphore, if all become available within the given waiting time and
     * the current thread has not been {@linkplain Thread#interrupt interrupted}.
     * 如果在指定等待时间内指定数量的许可变得可用并且当前线程被中断则从当前信号量中获取指定数量的许可。
     * <p>
     * Acquires the given number of permits, if they are available and returns immediately, with the value {@code true},
     * reducing the number of available permits by the given amount.
     * 获取指定数量的许可,如果可用则随着true理解返回,并减少指定数量的可用许可。
     * <p>
     * If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes and lies
     * dormant until one of three things happens:
     * 如果可用许可数量不足则当前线程处于线程调度目的将变得不可用并且休眠至三种情况中的其中一种发生:
     * <ul>
     * <li>Some other thread invokes one of the {@link #release() release} methods for this semaphore, the current thread is
     * next to be assigned permits and the number of available permits satisfies this request; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or
     * <li>The specified waiting time elapses.
     * </ul>
     * 某些其它线程调用当前信号量的release()方法之一,当前线程被下个分配许可并且可用许可数量满足要求;或者某些线程中
     * 断当前线程;或者指定等待时间消逝。
     * <p>
     * If the permits are acquired then the value {@code true} is returned.
     * 如果许可被获取则将返回true。
     * <p>
     * If the current thread:
     * 如果当前线程:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting to acquire the permits,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's interrupted status is cleared. Any permits that
     * were to be assigned to this thread, are instead assigned to other threads trying to acquire permits, as if the permits
     * had been made available by a call to {@link #release()}.
     * 在进入当前方法前/是被设置中断状态;或者在等待获取许可期间被中断,那么将抛出中断异常并且清除中断状态。任意被
     * 分配给当前线程的许可都将转而分配给其它尝试获取许可的线程,就好像这些线程通过调用release()方法变得可用一样。
     * <p>
     * If the specified waiting time elapses then the value {@code false} is returned.  If the time is less than or equal to zero,
     * the method will not wait at all.  Any permits that were to be assigned to this thread, are instead assigned to other
     * threads trying to acquire permits, as if the permits had been made available by a call to {@link #release()}.
     * 如果指定等待时间消逝则返回false。如果时间小于等待0则当前方法不会等待。任意被分配给当前线程的许可都将转而分配
     * 给其它尝试获取许可的线程,就好像这些线程通过调用release()方法变得可用一样。
     *
     * @param permits the number of permits to acquire 用以获取的许可数量
     * @param timeout the maximum time to wait for the permits 等待许可的最大时间
     * @param unit    the time unit of the {@code timeout} argument 超时参数的时间单位
     * @return {@code true} if all permits were acquired and {@code false} if the waiting time elapsed before all permits
     * were acquired
     * 如果指定数量的许可获取成功则返回true;如果等待时间在许可获取之前消逝则返回false
     * @throws InterruptedException     if the current thread is interrupted
     *                                  中断异常:如果当前线程被中断
     * @throws IllegalArgumentException if {@code permits} is negative
     *                                  非法参数异常:如果许可为负
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 尝试获取
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中获取指定数量的许可,其本质是减少许可的数量。如果存在足够的可用许可则返回true;否则在指定等待
     * 时间内等待至存在足够的可用许可为止。超时则返回false。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可是否合法,不合法则抛出非法参数异常;否则直接通过[同步]的
     * tryAcquireSharedNanos(int arg, long nanosTimeout)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
        // 许可的数量需要合法。
        if (permits < 0) {
            throw new IllegalArgumentException();
        }
        return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
    }

    /**
     * Releases the given number of permits, returning them to the semaphore.
     * 释放指定数量的许可,返回至信号量。
     * <p>
     * Releases the given number of permits, increasing the number of available permits by that amount. If any threads are
     * trying to acquire permits, then one is selected and given the permits that were just released. If the number of available
     * permits satisfies that thread's request then that thread is (re)enabled for thread scheduling purposes; otherwise the
     * thread will wait until sufficient permits are available. If there are still permits available after this thread's request
     * has been satisfied, then those permits are assigned in turn to other threads trying to acquire permits.
     * 释放指定数量的许可,递增该总数的可用许可数量。如果任意线程尝试获取许可,那么选择一个并给予刚释放的许可。如果
     * 可用许可数量满足线程的请求那么线程将处于线程调度的目的重新可用;否则线程将等待至足够的许可变得可用。如果在线
     * 程的请求满足后依然有许可可用,那么这些许可会被转而分配给其它尝试获取许可的线程。
     * <p>
     * There is no requirement that a thread that releases a permit must have acquired that permit by calling
     * {@link Semaphore#acquire acquire}. Correct usage of a semaphore is established by programming convention in the
     * application.
     * 释放许可的线程不要求必须通过acquire()方法获取许可。信号量的正确使用是通过程序中的编程协定确定的。
     *
     * @param permits the number of permits to release
     * @throws IllegalArgumentException if {@code permits} is negative
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 释放
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 为当前信号量中释放指定数量的许可,其本质是增加许可的数量。即方法不要求释放许可的线程必须获取过许可。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可是否合法,不合法则抛出非法参数异常;否则直接通过[同步]的
     * releaseShared(int arg, long nanosTimeout)方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public void release(int permits) {
        // 许可的数量需要合法。
        if (permits < 0) {
            throw new IllegalArgumentException();
        }
        sync.releaseShared(permits);
    }

    /**
     * Returns the current number of permits available in this semaphore.
     * 返回在当前信号量中可用许可的当前数量。
     * <p>
     * This method is typically used for debugging and testing purposes.
     * 该方法通常用于调式和测试目的
     *
     * @return the number of permits available in this semaphore 在当前信号量中可用许可的当前数量
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 可用许可
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 获取当前信号量的可用许可数量
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过调用[同步]的getPermits()方法实现,其本质是调用AQS的getState()方法。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public int availablePermits() {
        // 获取剩余的可用许可。
        return sync.getPermits();
    }

    /**
     * Acquires and returns all permits that are immediately available.
     * 获取并立即返回所有的可用许可。
     *
     * @return the number of permits acquired 获取的许可数量
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 流失许可
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 清除并获取当前信号量的所有可用许可数量
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过调用[同步]drainPermits()方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public int drainPermits() {
        // 清除剩余的可用许可。
        return sync.drainPermits();
    }

    /**
     * Shrinks the number of available permits by the indicated reduction. This method can be useful in subclasses that use
     * semaphores to track resources that become unavailable. This method differs from {@code acquire} in that it does not
     * block waiting for permits to become available.
     * 通过表示减少收缩可用许可的数量。该方法可在使用信号量追踪变得不可用的资源的子类中使用。该方法与获取方法不同
     * 在于不会阻塞等待许可变得可用。
     *
     * @param reduction the number of permits to remove 移除的许可数量
     * @throws IllegalArgumentException if {@code reduction} is negative
     *                                  非法参数异常:如果许可为负
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 减少许可
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 从当前信号量中减少指定数量的许可,其与获取方法的差别在于无论是否存在可用许可都可减少。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法首先会判断指定数量许可使用合法,否则抛出非法参数异常;是则直接通过调用[同步]reducePermits()方法减少许可。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    protected void reducePermits(int reduction) {
        // 许可的数量需要合法。
        if (reduction < 0) {
            throw new IllegalArgumentException();
        }
        sync.reducePermits(reduction);
    }

    /**
     * Returns {@code true} if this semaphore has fairness set true.
     * 如果当前信号量的公平性被设置为true则返回true。
     *
     * @return {@code true} if this semaphore has fairness set true 如果当前信号量的公平性被设置为true则返回true
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 是否公平
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 判断当前信号量是否公平,是则返回true;否则返回false。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法通过直接判断[同步]是否属于公平类型实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public boolean isFair() {
        // 判断是否公平。
        return sync instanceof FairSync;
    }

    /**
     * Queries whether any threads are waiting to acquire. Note that because cancellations may occur at any time, a
     * {@code true} return does not guarantee that any other thread will ever acquire. This method is designed primarily for
     * use in monitoring of the system state.
     * 查询任意线程是否正在等待获取。注意:因为取消可能在任意时间发生,因此返回true无法保证任意其它线程一直获取(即
     * 返回时线程可能已经因为获取成功/失败而结束获取)。该方法主要被设计用于监控系统状态。
     *
     * @return {@code true} if there may be other threads waiting to acquire the lock
     * 如果可能有其它线程等待获取锁则返回true
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 存在排队线程
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 判断当前信号量是否存在正在等待获取许可的线程,是则返回true;否则返回false。该方法的返回值无法作为准确的判断
     * 依据。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的hasQueuedThreads()方法实现。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    /**
     * Returns an estimate of the number of threads waiting to acquire. The value is only an estimate because the number of
     * threads may change dynamically while this method traverses internal data structures.  This method is designed for use
     * in monitoring of the system state, not for synchronization control.
     * 返回正在等待获取的线程的数量估计。该值只是一个估计因为线程数量可能在方法通过内部数据结构(即遍历同步队列)期
     * 间动态的改变。该方法被设计用于监控系统状态,无法用于同步控制。
     *
     * @return the estimated number of threads waiting for this lock 等待锁的线程估计值
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取队列长度
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 获取当前信号量中正在等待获取许可的线程数量的估计值。该方法的返回值无法作为准确的判断依据。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的getQueueLength()方法实现,底层逻辑是通过遍历同步队列来计算长度。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    /**
     * Returns a collection containing threads that may be waiting to acquire. Because the actual set of threads may change
     * dynamically while constructing this result, the returned collection is only a best-effort estimate. The elements of the
     * returned collection are in no particular order.  This method is designed to facilitate construction of subclasses that
     * provide more extensive monitoring facilities.
     * 返回包含可能正在等待获取的线程的集。因为线程的实际集合可能在构造结果期间动态的改变,因此返回的集只是一个尽
     * 力而为的估计值。返回集中的元素不按指定顺序排列。该方法被设计用于促进子类构造提供更多衍生监控设备。
     *
     * @return the collection of threads 线程集合
     * @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------
     * 获取排队线程
     * @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------
     * 获取当前信号量中可能正在等待获取许可的线程。该方法的返回值无法作为准确的判断依据。
     * @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------
     * 方法直接通过[同步]的getQueuedThreads()方法实现,底层逻辑是通过遍历同步队列来获取所有等待中的线程。
     * @Description: ------------------------------------------------------------- 注意 -------------------------------------------------------------
     * ~
     * @Description: ------------------------------------------------------------- 疑问 -------------------------------------------------------------
     * ~
     */
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    /**
     * Returns a string identifying this semaphore, as well as its state.
     * The state, in brackets, includes the String {@code "Permits ="}
     * followed by the number of permits.
     *
     * @return a string identifying this semaphore, as well as its state
     */
    public String toString() {
        return super.toString() + "[Permits = " + sync.getPermits() + "]";
    }
}















http://www.kler.cn/a/371888.html

相关文章:

  • net mvc中使用vue自定义组件遇到的坑
  • 【网络面试篇】TCP与UDP类
  • 字符串-05-字符串合并处理
  • Docker-微服务项目部署
  • 在 Elasticsearch 中顺利管理季节性时间变化
  • Web 核心指标优化之 INP 篇
  • Jenkins面试整理-什么是 Jenkins?
  • kettle8.3 Oracle连接运行一段时间后:Socket read timed out
  • ClickHouse 3节点集群安装
  • 香橙派Orangepi 5plus 配置Hailo-8/Hailo-8L
  • mariadb数据库中文乱码问题
  • 微服务之链路追踪Sleuth+zipkin
  • Linux 上使用 Docker 下载和运行 Redis
  • 智能家居10G雷达感应开关模块,飞睿智能uA级别低功耗、超高灵敏度,瞬间响应快
  • Web3的去中心化社交网络:区块链技术如何改变互动方式
  • 【ArcGISPro】制作简单的ArcGISPro-AI助手
  • HTML入门教程4:HTML属性
  • Android Studio Ladybug升级老项目遇到问题
  • 384.打乱数组
  • 单细胞数据分析(三):单细胞聚类分析
  • Linux上 Git 的简介、安装及操作详解(操作windows、linux通用)
  • LeetCode583:两个字符串的删除操作
  • windows server 2008 建立ftp服务器
  • QT linux 打包时库和插件如何生成
  • 嵌入式浏览器 -- Chromium VS Firefox
  • 国内对接使用GPT解决方案——API中转