Kir*_*ril 5 semaphore channel go goroutine
我有一个整数片,它们被同时操作:
ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Run Code Online (Sandbox Code Playgroud)
我使用缓冲通道作为信号量,以便具有同时运行的例程的上限:
sem := make(chan struct{}, 2)
for _, i := range ints {
// acquire semaphore
sem <- struct{}{}
// start long running go routine
go func(id int, sem chan struct{}) {
// do something
// release semaphore
<- sem
}(i, sem)
}
Run Code Online (Sandbox Code Playgroud)
上面的代码可以很好地工作,直到达到最后或最后两个整数,因为程序在最后一个例程完成之前结束.
问题:如何等待缓冲通道耗尽?
Jim*_*imB 14
您不能以这种方式使用信号量(在这种情况下是通道).在处理值和派遣更多goroutine时,无法保证它不会为空.在这种情况下,这并不是特别关注,因为你是同步调度工作,但是因为没有无竞争方法来检查通道的长度,所以没有原语可以等待通道的长度达到0.
使用a sync.WaitGroup等待所有goroutine完成
sem := make(chan struct{}, 2)
var wg sync.WaitGroup
for _, i := range ints {
wg.Add(1)
// acquire semaphore
sem <- struct{}{}
// start long running go routine
go func(id int) {
defer wg.Done()
// do something
// release semaphore
<-sem
}(i)
}
wg.Wait()
Run Code Online (Sandbox Code Playgroud)
使用“工作池”来处理您的数据。它比为每个int 运行 goroutine、为其中的变量分配内存等等更便宜......
ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
ch := make(chan int)
var wg sync.WaitGroup
// run worker pool
for i := 2; i > 0; i-- {
wg.Add(1)
go func() {
defer wg.Done()
for id := range ch {
// do something
fmt.Println(id)
}
}()
}
// send ints to workers
for _, i := range ints {
ch <- i
}
close(ch)
wg.Wait()
Run Code Online (Sandbox Code Playgroud)