**
* 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()方法都添加一个证书,潜在地释放一个阻塞的
acquirer请求。
然而,并没有真正的许可证书对象呗使用。Semaphore仅仅记录了一个可用数字的总量,起这相应的作用。
*
* <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:
Semaphores 经常用于约束一些线程,这些线程可以访问一些数据(物理的或者逻辑上的)。
例如,这里是一类 使用一个信号量控制池的访问。
* <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
*
* protected Object[] items = ... whatever kinds of items being managed
* 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];
* }
* }
* return null; // not reached
* }
*
* 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.
在获取一项时每个线程必须从信号量中请求一个许可证书。保证每一项都是可用的。当一个带有许可证的线程完成了
线程将返回到池中,并且许可证书归还给信号量,以让其他线程请求它(许可证书)。
注意没有synchronization锁当acueire方法调用的时候,因为要避免这一项(许可证书)此时归还到池中。
*
* <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 java.util.concurrent.locks.Lock}
* implementations), that the "lock" 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时,那么最多只有一个许可证书可被使用,可用作互斥锁。更被普遍所知的称为
二进制信号量,因为它仅有两个状态:1是可用或者0是可用。当这样使用时,二进制信号量有这样的
特性(不像很多的java.util.concurrent.locks.Lock实现),这个锁可以被其他线程而不是本线程释放
(因为semaphores没有所属关系的概念)。这是有用的在一些特定的上下文中,例如死锁恢复。
*
* <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.
*
该类的构造器可选择接受一个fairness参数。当设置为false时,该类不保证线程获取许可证书的顺序。
特殊地闯进的线程可能其他正在等待的线程前被许可,就是说一个线程调用acquire方法被分配一个许可证书
在其他等在的线程前。逻辑上一个新线程将放入到线程等待队列头部。当fairness被设置为true时,这个
semaphore保证调用acquire方法的线程按照它们调用那些方法的顺序获取许可证书(先进先出FIFO)。注意
FIFO排序需要应用在内部特定的一些方法中。因此,一个线程可能在另一个县城前调用acquire方法,但是
在另一个线程后到达排序点,并从方法中返回。同时注意,不记时的方法(tryAcquire())不会遵守fairness设置,并获取任何可用的许可。
* <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.
通常,用于控制资源访问的semaphores应该初始化为公平设置,确保不会有线程因访问资源二死亡。
当使用semaphores作为其他同步控制时,非公平顺序的吞吐量的优势通常要超过公平角度的考虑。
*
* <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.
该类同样提供了方便的方法去同时请求(acquire(int))和释放(release(int))多个许
的方法。要注意不设置fairness 为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.
内存一致性影响:
*
* @since 1.5
* @author Doug Lea
*/
与lock或者synchronized只允许某时刻一个任务访问资源,Semaphore可以多个任务访问资源。(《Java编程思想》P1246)