2018-10-02
原文推薦 死磕Java并發(fā)
信號量Semaphore是一個控制訪問多個共享資源的計數(shù)器,和CountDownLatch一樣,其本質(zhì)上是一個“共享鎖”。
Semaphore,在API是這么介紹的:
一個計數(shù)信號量。從概念上講,信號量維護(hù)了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然后再獲取該許可。每個 release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實(shí)際的許可對象,Semaphore 只對可用許可的號碼進(jìn)行計數(shù),并采取相應(yīng)的行動。
Semaphore 通常用于限制可以訪問某些資源(物理或邏輯的)的線程數(shù)目。
下面我們就一個停車場的簡單例子來闡述Semaphore:
為了簡單起見我們假設(shè)停車場僅有5個停車位,一開始停車場沒有車輛所有車位全部空著,然后先后到來三輛車,停車場車位夠,安排進(jìn)去停車,然后又來三輛,這個時候由于只有兩個停車位,所有只能停兩輛,其余一輛必須在外面候著,直到停車場有空車位,當(dāng)然以后每來一輛都需要在外面候著。當(dāng)停車場有車開出去,里面有空位了,則安排一輛車進(jìn)去(至于是哪輛 要看選擇的機(jī)制是公平還是非公平)。
從程序角度看,停車場就相當(dāng)于信號量Semaphore,其中許可數(shù)為5,車輛就相對線程。當(dāng)來一輛車時,許可數(shù)就會減 1 ,當(dāng)停車場沒有車位了(許可數(shù) == 0 ),其他來的車輛需要在外面等候著。如果有一輛車開出停車場,許可數(shù) + 1,然后放進(jìn)來一輛車。
信號量Semaphore是一個非負(fù)整數(shù)(>=1)。當(dāng)一個線程想要訪問某個共享資源時,它必須要先獲取Semaphore,當(dāng)Semaphore >0時,獲取該資源并使Semaphore – 1。如果Semaphore值 = 0,則表示全部的共享資源已經(jīng)被其他線程全部占用,線程必須要等待其他線程釋放資源。當(dāng)線程釋放資源時,Semaphore則+1
public class SemaphoreTest {
static class Parking{
//信號量
private Semaphore semaphore;
Parking(int count){
semaphore = new Semaphore(count);
}
public void park(){
try {
//獲取信號量
semaphore.acquire();
long time = (long) (Math.random() * 10);
System.out.println(Thread.currentThread().getName() + "進(jìn)入停車場,停車" + time + "秒..." );
Thread.sleep(time);
System.out.println(Thread.currentThread().getName() + "開出停車場...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}
static class Car extends Thread {
Parking parking ;
Car(Parking parking){
this.parking = parking;
}
@Override
public void run() {
parking.park(); //進(jìn)入停車場
}
}
public static void main(String[] args){
Parking parking = new Parking(3);
for(int i = 0 ; i < 5 ; i++){
new Car(parking).start();
}
}
}