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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM