Semaphore 信号量

一个计数信号量。从概念上讲,信号量维护了一个许可集。若有必要,在许可可用前会阻塞每个 acquire(),而后再获取该许可。每一个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。编程

可是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采起相应的行动。拿到信号量的线程能够进入代码,不然就等待。经过acquire()和release()获取和释放访问许可。dom

 1 acquire
 2 public void acquire()
 3              throws InterruptedException
 4 今后信号量获取一个许可,在提供一个许可前一直将线程阻塞,不然线程被中断。获取一个许可(若是提供了一个)并当即返回,将可用的许可数减 1 5 若是没有可用的许可,则在发生如下两种状况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态:
 6 某些其余线程调用此信号量的 release() 方法,而且当前线程是下一个要被分配许可的线程;或者
 7 其余某些线程中断当前线程。
 8 若是当前线程:
 9 被此方法将其已中断状态设置为 on ;或者
10 在等待许可时被中断。
11 则抛出 InterruptedException,而且清除当前线程的已中断状态。 
12 抛出:
13 InterruptedException - 若是当前线程被中断
1 release
2 public void release()
3 释放一个许可,将其返回给信号量。释放一个许可,将可用的许可数增长 1。若是任意线程试图获取许可,则选中一个线程并将刚刚释放的许可给予它。而后针对线程安排目的启用(或再启用)该线程。
4 不要求释放许可的线程必须经过调用 acquire() 来获取许可。经过应用程序中的编程约定来创建信号量的正确用法。

下面的例子只容许5个线程同时进入执行acquire()和release()之间的代码:ui

 1 public class SemaphoreTest {
 2 
 3      public static void main(String[] args) {  
 4         // 线程池 
 5         ExecutorService exec = Executors.newCachedThreadPool();  
 6         // 只能5个线程同时访问 
 7         final Semaphore semp = new Semaphore(5);  
 8         // 模拟20个客户端访问 
 9         for (int index = 0; index < 20; index++) {
10             final int NO = index;  
11             Runnable run = new Runnable() {  
12                 public void run() {  
13                     try {  
14                         // 获取许可 
15                         semp.acquire();  
16                         System.out.println("Accessing: " + NO);  
17                         Thread.sleep((long) (Math.random() * 10000));  
18                         // 访问完后,释放 ,若是屏蔽下面的语句,则在控制台只能打印5条记录,以后线程一直阻塞
19                         semp.release();  
20                     } catch (InterruptedException e) {  
21                     }  
22                 }  
23             };  
24             exec.execute(run);  
25         }  
26         // 退出线程池 
27         exec.shutdown();  
28     }  
29 }

 比较形象的解释:spa

Semaphore分为单值和多值两种,前者只能被一个线程得到,后者能够被若干个线程得到。线程

Semaphore实现的功能就相似厕全部5个坑,假若有10我的要上厕所,那么同时只能有多少我的去上厕所呢?同时只能有5我的可以占用,当5我的中 的任何一我的让开后,其中等待的另外5我的中又有一我的能够占用了。另外等待的5我的中能够是随机得到优先机会,也能够是按照先来后到的顺序得到机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象能够实现互斥锁的功能,而且能够是由一个线程得到了“锁”,再由另外一个线程释放“锁”,这可应用于死锁恢复的一些场合。code

再以一个停车场运做为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时若是同时来了五辆车,看门人容许其中三辆不受阻碍的进入,而后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,若是又离开两辆,则又能够放入两辆,如此往复。对象

在这个停车场系统中,车位是公共资源,每辆车比如一个线程,看门人起的就是信号量的做用。blog

更进一步,信号量的特性以下:信号量是一个非负整数(车位数),全部经过它的线程(车辆)都会将该整数减一(使用资源),当该整数值为零时,全部试图经过它的线程都将处于等待状态。在信号量上咱们定义两种操做: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操做时,它要么经过而后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)其实是在信号量上执行加操做,对应于车辆离开停车场,该操做之因此叫作“释放”是由于加操做其实是释放了由信号量守护的资源。队列

Semaphore(int permits, boolean fair)
//建立具备给定的许可数和给定的公平设置的Semaphore。

还能够设置该信号量是否采用公平模式,若是以公平方式执行,则线程将会按到达的顺序(FIFO)执行,若是是非公平,则能够后请求的有可能排在队列的头部。资源

相关文章
相关标签/搜索