Semaphore
Semaphore 訊號量:可以用來控制同時訪問特定資源的執行緒數量;通過協調各個執行緒以保證合理的使用公共資源。
構造
// permits 設定許可證的數量
public Semaphore(int permits) {
// 預設非公平
sync = new NonfairSync(permits);
}
// permits 設定許可數量
// fair 設定是否採用公平模式
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
複製程式碼
非公平模式
acquire()
獲取許可。只有當獲取到可用的許可,或者當前執行緒被中斷;否則該執行緒被阻塞
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
複製程式碼
預設會呼叫 NonfairSync 下的 tryAcquireShared 方法,繼續呼叫父類的 nonfairTryAcquireShared 方法
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
複製程式碼
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
// 獲取當前 state 值
// 也即是當前可用的許可數
int available = getState();
// 當前可用許可數減去嘗試獲取許可的數
// 得到剩餘許可數
int remaining = available - acquires;
// remaining < 0 說明當前可用許可數小於嘗試獲取許可數,也即是獲取同步狀態失敗 直接返回 remaining, 退出迴圈 當前執行緒會被新增到同步佇列中
// remaining > 0 說明當前可用許可數大於嘗試獲取許可數,
// 則執行 compareAndSetState 更新 state , 若更新成功則返回 退出迴圈 當前執行緒獲取到許可
// 若 compareAndSetState 更新失敗,說明有其他執行緒獲取到許可,則繼續輪詢
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
複製程式碼
release
釋放許可
public void release() {
sync.releaseShared(1);
}
複製程式碼
protected final boolean tryReleaseShared(int releases) {
for (;;) {
// 獲取當前許可數
int current = getState();
// 當前許可 + 釋放的許可數
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
// 更新 state 值, 更新成功則返回 true 退出迴圈;並喚醒同步佇列上阻塞的執行緒
// 更新 state 值失敗,說明有其他執行緒獲取許可或釋放了許可,則繼續輪詢
if (compareAndSetState(current, next))
return true;
}
}
複製程式碼
公平模式
acquire
公平模式下獲取許可
protected int tryAcquireShared(int acquires) {
for (;;) {
// 判斷同步佇列上是否有阻塞的執行緒
// 若有的話,返回 -1 表示獲取許可失敗 退出迴圈加入同步佇列中
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
複製程式碼
從上述程式碼中可以看到,公平模式下獲取許可和非公平模式下基本類似,只是為了保證 FIFO ,新增了 hasQueuedPredecessors 判斷限制。
release
公平模式下與非公平模式一樣
小結
Semaphore 可以用來實現限流的作用。