天天看點

Java多線程并發工具類-信号量Semaphore對象講解

Java多線程并發工具類-信号量Semaphore對象講解

Java多線程并發工具類-Semaphore對象講解

通過前面的學習,我們已經知道了Java多線程并發場景中使用比較多的兩個工具類:做加法的CycliBarrier對象以及做減法的CountDownLatch對象并對這兩個對象進行了比較。我們發現這兩個對象要麼是做加法,要麼是做減法的。那麼有沒有既做加法也做減法的呢?當然有了。Semaphore這個工具類就可以實作One out one in的。

本文主要内容:Semaphore是什麼?從生活中例子中來了解Semaphore;代碼示範;總結。通過總結-了解-代碼示範-再總結這四個步驟讓大家來深刻的了解。

本篇是《凱哥(凱哥Java:kagejava)并發程式設計學習》系列之《并發工具類》教程的第三篇:《Java多線程下信号量》。

一:Semaphore是什麼?

Semaphore中文意思:信号量。

來看看JavaAPI中對semaphore對象的解釋:

什麼意思呢?

簡單了解來說,Semaphore:信号量主要用于兩個目的:一個是用于多個共享資源的互斥使用;另一個用于并發線程數量的控制。什麼意思呢?我們來從生活中的例子來了解。

二:從生活中例子中來了解Semaphore

案例一:搶車位

自駕遊的朋友一般都會遇到這樣的煩惱:去景區遊玩,停車比較麻煩。因為停車場中的車位數量是一定的。當車位滿了以後,其他想要進入停車場停車的車輛隻能等待。等到其他車輛出來之後,才可以進入。站在并發角度來分析的話:停車場有多個停車位(多個共享資源),每個車輛隻能停在其中一個位置上(互斥使用的),停車場的停車位是固定的(并發線程數量的控制)。這樣是不是就好了解了?如果還是不好了解,接着看下面這個案例

案例二:海底撈吃火鍋

去海底撈吃火鍋的時候,海底撈場地就餐桌數量是固定的,假設有5桌。現在來了8個人,那麼其他3個就需要在門口候餐區等待加号。當有其他桌吃完離開之後,進去一個。簡圖如下:

三:代碼示範

我們就來模拟海底撈吃火鍋的場景。

3.1:為什麼要使用Semaphore?

為什麼不能使用其他兩個同步工具類呢?

根據CountDownLatch的特性,隻能使用一次的特征來說,海底撈這種場景當然不能夠使用了。因為開個店不可能隻使用一次。

CyclicBarrier,雖然可以使用多次,但是需要reset之後才可以多次使用。意思就是,隻有等餐廳裡面5個桌的客人都吃完之後,才可以讓其他人進來就餐的。這種情況也是不符合業務邏輯的。

而Semaphore可以做到One out One in 很适合海底撈的場景。是以,經過分析,我們可以得到如下代碼。

代碼示範:

餐桌對象:

執行方法:

運作結果:

從運作結果中,我們可以看到一個進入一個就離開,一個離開餐桌下一位就進入餐廳就餐。達到我們預期結果了。

四:總結

4.1:使用文法

在聲明smaphore的時候需要設定線程數量。然後使用acquire擷取資源。在finally方法裡面調用release方法進行釋放資源。如下圖:

4.2:内部主要組成

4.2.1:三個内部類:

看到這三個類是不是很熟悉?對就是我們前面介紹的ReentrantLock和ReentrantReadWriteLock這兩個對象裡面都存在的。繼承AQS的Sync類以及公平鎖的FairSync類和非公平鎖的NonfairSync類。同樣,semaphore也支援在構造器中指定是公平還是非公平的:

4.2.2:主要方法

重要的方法擷取和釋放方法:

擷取資源的:

acquire()/acquire(int permits):擷取資源(許可證)/擷取指定個數的資源

釋放資源:

release()/release(int permits):釋放資源/釋放指定個數的資源

其他方法:

阻止擷取資源:

acquireUninterruptibly()/acquireUninterruptibly(int permits):從這個信号燈擷取許可證,阻止一個可用的/阻止指定數量的

擷取目前可以用的資源數量: int availablePermits()

還有其他很多方法。凱哥這裡就不一一介紹了。大家可以自行檢視API

4.3:實作原理

看到Sync這個内部類之後,大家就應該想到了凱哥(kaigejava)在之前介紹過的AQS對象了。沒錯,Semaphore就是使用AQS和CAS來實作資源的擷取和釋放的。在這裡凱哥就不贅述了。大家可以看看前面凱哥介紹并發容器的同步器相關文章,裡面凱哥做了詳細的介紹。

原文位址

https://www.cnblogs.com/kaigejava/p/12683778.html