作者: 西魏陶淵明
部落格: https://blog.springlearn.cn/
西魏陶淵明
莫笑少年江湖夢,誰不少年夢江湖
🚀 知識快讀
Semaphore
翻譯過來就是信号量, 其根本原理就是基于
CAS
共享鎖的一種實作。舉一個例子。
假設停車場隻有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看門人允許其中三輛不受阻礙的進入,然後放下車攔,剩下的車則必須在入口等待,此後來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知後,打開車攔,放入一輛,如果又離開兩輛,則又可以放入兩輛,如此往複。
那麼上面的這個例子可以這樣了解,資源一共有3個, 即三個車位。如何來控制這5輛汽車,來合理的使用這3個資源呢?
Semaphore
可以這樣來定義。
// 1. 定一個信号量,聲明有3個資源。使用公平模式線程将會按到達的順序(FIFO)執行(也就是等待時間最長的先執行),如果是非公平,則可以後請求的有可能排在隊列的頭部。
Semaphore semp = new Semaphore(3);
// 2. 擷取1個許可 - 最大允許3個進入,一但超過就讓其等待,除非已經釋放
semp.acquire();
// 3. 釋放1個許可
semp.release();
// 4. 擷取1許可,失敗就傳回,不等待
semp.tryAcquire();
// 5. 擷取2許可,失敗就傳回,不等待
semp.tryAcquire(2);
// 6. 不允許被中斷
semp.acquireUninterruptibly();
知識點1: Fair & NoFair
- 預設構造不公平模式, 誰來申請資源,就先嘗試擷取資源。排隊的要等到沒有資源進來申請才能繼續申請
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
知識點2: 申請資源
- acquire() 擷取1個資源,擷取不到就等待,如果線程中斷,會直接中斷。
- acquire(2) 擷取2個資源,擷取不到就等待,如果線程中斷,會直接中斷。
- tryAcquire() 擷取1個資源,擷取不到就傳回
,如果線程中斷,會直接中斷。false
- acquireUninterruptibly() 擷取1個資源,擷取不到就等待,不會關心線程中斷。
知識點3: 釋放資源
- release() 釋放一個資源
- release(2) 釋放兩個資源
知識點4: 其他API
- availablePermits() 目前資源數量
- drainPermits() 擷取目前資源數量,并将剩餘資源清零,直接指派0
- reducePermits(2) 将資源數量,扣減2個
- isFair() 是否公平
- hasQueuedThreads() 是否還有線程等待
- getQueueLength() 還有多少線程等待
- getQueuedThreads() 擷取所有的線程集合