semaphore有兩種模式,公平模式和非公平模式。公平模式就是呼叫acquire的順序就是獲取許可證的順序,遵循fifo;而非公平模式是搶占式的,也就是有可能乙個新的獲取執行緒恰好在乙個許可證釋放時得到了這個許可證,而前面還有等待的執行緒。
semaphore有兩個構造方法,如下:
public
semaphore(int permits)
public
semaphore(int permits, boolean fair)
從上面可以看到兩個構造方法,都必須提供許可的數量,第二個構造方法可以指定是公平模式還是非公平模式,預設非公平模式。
semaphore內部基於aqs的共享模式,所以實現都委託給了sync類。
這裡就看一下nonfairsync的構造方法:
nonfairsync(int permits)
可以看到直接呼叫了父類的構造方法,sync的構造方法如下:
sync(int permits)
可以看到呼叫了setstate方法,也就是說aqs中的資源就是許可證的數量。
先從獲取乙個許可看起,並且先看非公平模式下的實現。首先看acquire方法,acquire方法有幾個過載,但主要是下面這個方法
public
void
acquire(int permits) throws interruptedexception
從上面可以看到,呼叫了sync的acquiresharedinterruptibly方法,該方法在父類aqs中,如下:
public
final
void
acquiresharedinterruptibly(int arg)
throws interruptedexception
aqs子類如果要使用共享模式的話,需要實現tryacquireshared方法,下面看nonfairsync的該方法實現:
protected
inttryacquireshared(int acquires)
該方法呼叫了父類中的nonfairtyacquireshared方法,如下:
final
int nonfairtryacquireshared(int acquires)
}
從上面可以看到,只有在許可不夠時返回值才會小於0,其餘返回的都是剩餘許可數量,這也就解釋了,一旦許可不夠,後面的執行緒將會阻塞。看完了非公平的獲取,再看下公平的獲取,**如下:
protected
inttryacquireshared(int acquires)
}
從上面可以看到,fairsync與nonfairsync的區別就在於會首先判斷當前佇列中有沒有執行緒在等待,如果有,就老老實實進入到等待佇列;而不像nonfairsync一樣首先試一把,說不定就恰好獲得了乙個許可,這樣就可以插隊了。
看完了獲取許可後,再看一下釋放許可。
釋放許可也有幾個過載方法,但都會呼叫下面這個帶引數的方法,
public
void
release(int permits)
releaseshared方法在aqs中,如下:
public
final
boolean
releaseshared(int arg)
return
false;
}
aqs子類實現共享模式的類需要實現tryreleaseshared類來判斷是否釋放成功,實現如下:
protected
final
boolean
tryreleaseshared(int releases)
}
從上面可以看到,一旦cas改變許可數量成功,那麼就會呼叫doreleaseshared()方法釋放阻塞的執行緒。
semaphore還有減小許可數量的方法,該方法可以用於用於當資源用完不能再用時,這時就可以減小許可證。**如下:
protected
void
reducepermits(int reduction)
可以看到,委託給了sync,sync的reducepermits方法如下:
final
void reducepermits(int reductions)
}
從上面可以看到,就是cas改變aqs中的state變數,因為該變數代表許可證的數量。
semaphore還可以一次將剩餘的許可數量全部取走,該方法是drain方法,如下:
public
intdrainpermits()
sync的實現如下:
final
int drainpermits()
}
可以看到,就是cas將許可數量置為0。
semaphore是訊號量,用於管理一組資源。其內部是基於aqs的共享模式,aqs的狀態表示許可證的數量,在許可證數量不夠時,執行緒將會被掛起;而一旦有乙個執行緒釋放乙個資源,那麼就有可能重新喚醒等待佇列中的執行緒繼續執行。
原始碼分析 Semaphore
計數訊號量,從概念上說,訊號量維持了一些許可。public class semaphoretest start protected void getinfo catch exception e finally 他會2每秒列印10個值,沒10個執行緒 獲取許可,其他執行緒會被阻塞在semaphore....
併發程式設計之 Semaphore 原始碼分析
併發 juc 包提供了很多任務具類,比如之前說的 countdownlatch,cyclicbarrier 今天說說這個 semaphore 訊號量,關於他的使用請檢視往期文章併發程式設計之 執行緒協作工具類,今天的任務就是從原始碼層面分析一下他的原理。如果先不看原始碼,根據以往我們看過的 coun...
Semaphore 原始碼解析
semaphore 訊號量 從概念上講,訊號量維護一套許可。每次 acquire 方法呼叫都會根據需要進行阻塞,直到獲得許可為止,然後將其占用。每次 release 方法呼叫都會新增乙個許可,可能會喚醒因沒有獲取到許可而阻塞的執行緒。semaphore 基於 aqs 實現,不熟悉 aqs 的同學可以...