JUC--并發(fā)工具類:Semaphore

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();
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容