Semaphore,动态增减信号量

我的理解~~

【信号量】:

  • 用于控制对某资源访问的同一时间的并发量。

【如何获取】:

  • semaphore.tryAcquire(),尝试获取,不阻塞
  • semaphore.acquire(),没信号量可用时,将进行阻塞等

【如何释放】:

  • semaphore.release();
  • 线程抛出各种异常,都别忘了在finally中释放信号量;
  • 如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了,要注意。

【动态增加】:

  • 多释放几次,就可以达到信号量动态增加的效果了

【动态减小】:

  • 信号量本来有这个api的,不过是protected方法,所以我们需要显式继续Semaphore,并重新实现该api,见ResizeableSemaphore类中的reducePermits(int reduction);
  • 举例如下:(该表格有个假设前提,不存在多余的release而产生出新的信号量,即release次数<=acquire次数)
当前信号量A
(A=A1+A2)
占用信号量A1 可用信号量A2 重新设置信号量B
(B=B1+B2)
当前可用的信号量B1 当前待释放的量B2
5 3 2 3 0 0
5 3 2 1 0 -2
5 3 2 9 6 0

image

【动态减小—demo】:

import java.util.concurrent.Semaphore;
 
 
public class AdjustableSemaphore {
 
    private final ResizeableSemaphore  semaphore = new ResizeableSemaphore();
    
    private int maxPermits = 0;
    
    public AdjustableSemaphore(){
        
    }
    
    synchronized void setMaxPermits(int newMax){
        if(newMax < 1){
            throw new IllegalArgumentException("Semaphore size must be at least 1,"
                + " was " + newMax);
        }
        
        int delta = newMax - this.maxPermits;
        
        if(delta == 0){
            return ;
        }else if(delta > 0){
            this.semaphore.release(delta);
        }else {
            delta *= -1;
            this.semaphore.reducePermits(delta);
        }
        
        this.maxPermits = newMax;
        
    }
    
    public int availablePermits(){
       return this.semaphore.availablePermits();
    }
    
    public void release(){
        this.semaphore.release();
    }
    
    public boolean tryAcquire(){
        return this.semaphore.tryAcquire();
    }
    
    
    
    
    private static final class ResizeableSemaphore extends Semaphore {
 
        ResizeableSemaphore(){
            super(0);
        }
        
        @Override
        protected void reducePermits(int reduction){
            super.reducePermits(reduction);
        }
        
    }
    
    
}
 
 
【测试程序】:
AdjustableSemaphore semaphore = new AdjustableSemaphore();
        System.out.println("==============5");
        semaphore.setMaxPermits(5);
        
        for(int i=0;i<20;i++){
            semaphore.tryAcquire();
        }
        
        
        System.out.println(semaphore.availablePermits()); //5个信号量全被占用,所以当前可用的为0
        
        
        System.out.println("==============2");
        semaphore.setMaxPermits(2);
        
        System.out.println(semaphore.availablePermits()); //将信号量显式设置为2,与上一步合并结果(2-5)=-3,表示目前有5个被占用,信号量只有2,所以还有3个欠着待释放
        
        
        System.out.println("==============20");
        semaphore.setMaxPermits(20);
        System.out.println(semaphore.availablePermits());//将信号量显式设置为20,与上一步合并结果(20-2)+(-3)=15个,表示目前还有15个可用。
        
        System.out.println("==============3");
        semaphore.setMaxPermits(3);
        System.out.println(semaphore.availablePermits());//同上,(3-20)+15=-2
        
        System.out.println("==============1");
        semaphore.setMaxPermits(1);
        System.out.println(semaphore.availablePermits());//同上,(1-3)-2=-4
        
        System.out.println("==============10");
        semaphore.setMaxPermits(10);
        System.out.println(semaphore.availablePermits());//同上,(10-1)-4=5
        
        System.out.println("==============FINALLY");
        for(int i=0;i<7;i++){
            semaphore.release();
        }
        System.out.println(semaphore.availablePermits());//释放了7个,所以7+5=12,虽然显式设置了信号量为10,但因多release()了两次,所以无意之中隐式增大了信号量。
 
 
 
【输出结果】:

==============5
0
==============2
-3
==============20
15
==============3
-2
==============1
-4
==============10
5
==============FINALLY
10

这里可参考:http://blog.teamlazerbeez.com/2009/04/20/javas-semaphore-resizing/

原文地址:https://www.cnblogs.com/alipayhutu/p/2518620.html