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