Java 信号量 Semaphore 介绍
2015-05-09 08:30
260 查看
简介
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,它负责协调各个线程,以保证它们能够正确、合理的使用公共资源。一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可。每个release()添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行计数,并采取相应的行动。拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。
Semaphore通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。
概念
Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。将信号量初始化为1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多
Lock实现不同),即可以由线程释放“锁”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
此类的构造方法可选地接受一个公平参数。当设置为false时,此类不对线程获取许可的顺序做任何保证。特别地,闯入是允许的,也就是说可以在已经等待的线程前为调用
acquire()的线程分配一个许可,从逻辑上说,就是新线程将自己置于等待线程队列的头部。当公平设置为true时,信号量保证对于任何调用
获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。注意,FIFO排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了
acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。还要注意,非同步的
tryAcquire方法不使用公平设置,而是使用任意可用的许可。
通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。
此类还提供便捷的方法来同时
acquire和
释放多个许可。小心,在未将公平设置为true时使用这些方法会增加不确定延期的风险。
内存一致性效果:线程中调用“释放”方法(比如
release())之前的操作
acquire())之后的操作。
公平模式:如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。
JDK中定义如下:
Semaphore(intpermits,booleanfair)
创建具有给定的许可数和给定的公平设置的Semaphore。
主要的方法:
构造方法摘要 | |||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Semaphore(intpermits) 创建具有给定的许可数和非公平的公平设置的 Semaphore。 | |||||||||||||||||||||||||||||||||||||
Semaphore(intpermits,booleanfair) 创建具有给定的许可数和给定的公平设置的
|
Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能,但实现上要复杂些。
下面的Demo中申明了一个只有5个许可的Semaphore,而有20个线程要访问这个资源,通过acquire()和release()获取和释放访问许可。
packagecom.dxz.semaphore;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.Semaphore;
publicclassTestSemaphore{
publicstaticvoidmain(String[]args){
//线程池
ExecutorServiceexec=Executors.newCachedThreadPool();
//只能5个线程同时访问
finalSemaphoresemp=newSemaphore(5);
//模拟20个客户端访问
for(intindex=0;index<20;index++){
finalintNO=index;
Runnablerun=newRunnable(){
publicvoidrun(){
try{
//获取许可
semp.acquire();
System.out.println("Accessing:"+NO);
Thread.sleep((long)(Math.random()*1000));
//访问完后,释放
semp.release();
System.out.println("semp.availablePermits()=="+semp.availablePermits());
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
};
exec.execute(run);
}
//退出线程池
exec.shutdown();
}
}
执行结果如下:
Accessing:0
Accessing:2
Accessing:4
Accessing:6
Accessing:8
semp.availablePermits()==0
Accessing:10
Accessing:12
semp.availablePermits()==0
semp.availablePermits()==1
Accessing:14
semp.availablePermits()==1
Accessing:16
semp.availablePermits()==1
Accessing:18
semp.availablePermits()==1
Accessing:1
semp.availablePermits()==1
Accessing:3
semp.availablePermits()==1
Accessing:5
semp.availablePermits()==1
Accessing:7
semp.availablePermits()==1
Accessing:9
semp.availablePermits()==1
Accessing:11
Accessing:13
semp.availablePermits()==0
semp.availablePermits()==1
Accessing:15
semp.availablePermits()==1
Accessing:17
semp.availablePermits()==1
Accessing:19
semp.availablePermits()==1
semp.availablePermits()==2
semp.availablePermits()==3
semp.availablePermits()==4
semp.availablePermits()==5
相关文章推荐
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java信号量 Semaphore 介绍
- 【转】Java 信号量 Semaphore 介绍
- Java信号量Semaphore 介绍
- 【转】Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍
- java多线程-Semaphore信号量使用 介绍 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源
- Java 信号量 Semaphore 介绍
- Java 信号量 Semaphore 介绍