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來實現資源的獲取和釋放的。在這裡凱哥就不贅述了。大家可以看看前面凱哥介紹併發容器的同步器相關文章,裡面凱哥做了詳細的介紹。
歡迎來