Go雖然天生的支持高并發(fā),但是有些場(chǎng)景下我們還是需要控制協(xié)程同時(shí)并發(fā)處理的數(shù)量,在Java的juc包中已經(jīng)提供了類(lèi)似功能的工具類(lèi)-信號(hào)量(Semaphore),它是基于AQS實(shí)現(xiàn)的。Go的SDK中并沒(méi)有提供類(lèi)似的API,我們通過(guò)goroutine和channel實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Semaphore,并提供:獲取許可(Acquire())、指定時(shí)間內(nèi)獲取許可(TryAcquireOnTime)、釋放許可(Release())等方法,具體實(shí)現(xiàn)如下:
type Semaphore struct {
permits int // 許可數(shù)量
channel chan int // 通道
}
/* 創(chuàng)建信號(hào)量 */
func NewSemaphore(permits int) *Semaphore {
return &Semaphore{channel: make(chan int, permits), permits: permits}
}
/* 獲取許可 */
func (s *Semaphore) Acquire() {
s.channel <- 0
}
/* 釋放許可 */
func (s *Semaphore) Release() {
<-s.channel
}
/* 嘗試獲取許可 */
func (s *Semaphore) TryAcquire() bool {
select {
case s.channel <- 0:
return true
default:
return false
}
}
/* 嘗試指定時(shí)間內(nèi)獲取許可 */
func (s *Semaphore) TryAcquireOnTime(timeout time.Duration) bool {
for {
select {
case s.channel <- 0:
return true
case <-time.After(timeout):
return false
}
}
}
/* 當(dāng)前可用的許可數(shù) */
func (s *Semaphore) AvailablePermits() int {
return s.permits - len(s.channel)
}