天天看點

JAVA多線程--信号量(Semaphore)簡介概念代碼示例

        信号量(semaphore),有時被稱為信号燈,是在多線程環境下使用的一種設施, 它負責協調各個線程, 以保證它們能夠正确、合理的使用公共資源。

        一個計數信号量。從概念上講,信号量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再擷取該許可。每個 release() 添加一個許可,進而可能釋放一個正在阻塞的擷取者。但是,不使用實際的許可對象,semaphore 隻對可用許可的号碼進行計數,并采取相應的行動。拿到信号量的線程可以進入代碼,否則就等待。通過acquire()和release()擷取和釋放通路許可。

        semaphore分為單值和多值兩種,前者隻能被一個線程獲得,後者可以被若幹個線程獲得。

     以一個停車場運作為例。為了簡單起見,假設停車場隻有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看門人允許其中三輛不受阻礙的進入,然後放下車攔,剩下的車則必須在入口等待,此後來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知後,打開車攔,放入一輛,如果又離開兩輛,則又可以放入兩輛,如此往複。

    在這個停車場系統中,車位是公共資源,每輛車好比一個線程,看門人起的就是信号量的作用。

    更進一步,信号量的特性如下:信号量是一個非負整數(車位數),所有通過它的線程(車輛)都會将該整數減一(通過它當然是為了使用資源),當該整數值為零時,所有試圖通過它的線程都将處于等待狀态。在信号量上我們定義兩種操作: wait(等待) 和 release(釋放)。 當一個線程調用wait(等待)操作時,它要麼通過然後将信号量減一,要麼一直等下去,直到信号量大于一或逾時。release(釋放)實際上是在信号量上執行加操作,對應于車輛離開停車場,該操作之是以叫做“釋放”是因為加操作實際上是釋放了由信号量守護的資源。

    在java中,還可以設定該信号量是否采用公平模式,如果以公平方式執行,則線程将會按到達的順序(fifo)執行,如果是非公平,則可以後請求的有可能排在隊列的頭部。

jdk中定義如下:

        semaphore(int permits, boolean fair)

     建立具有給定的許可數和給定的公平設定的semaphore。

    semaphore目前在多線程環境下被擴放使用,作業系統的信号量是個很重要的概念,在程序控制方面都有應用。java并發庫semaphore 可以很輕松完成信号量控制,semaphore可以控制某個資源可被同時通路的個數,通過 acquire() 擷取一個許可,如果沒有就等待,而 release() 釋放一個許可。比如在windows下可以設定共享檔案的最大用戶端通路個數。

    semaphore實作的功能就類似廁所有5個坑,假如有10個人要上廁所,那麼同時隻能有多少個人去上廁所呢?同時隻能有5個人能夠占用,當5個人中 的任何一個人讓開後,其中等待的另外5個人中又有一個人可以占用了。另外等待的5個人中可以是随機獲得優先機會,也可以是按照先來後到的順序獲得機會,這取決于構造semaphore對象時傳入的參數選項。單個信号量的semaphore對象可以實作互斥鎖的功能,并且可以是由一個線程獲得了“鎖”,再由另一個線程釋放“鎖”,這可應用于死鎖恢複的一些場合。