我有一个整数片,它们被同时操作:
ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
我使用缓冲通道作为信号量,以便具有同时运行的例程的上限:
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)
}
上面的代码可以很好地工作,直到达到最后或最后两个整数,因为程序在最后一个例程完成之前结束。
问题:如何等待缓冲通道耗尽?
答案 0 :(得分:11)
您不能以这种方式使用信号量(在这种情况下为频道)。当你处理价值并派遣更多的goroutines时,不能保证它在任何时候都不会是空的。在这种情况下,这并不是特别关注,因为您同步调度工作,但因为没有无种族方式来检查频道的长度,所以没有原语等待频道的长度达到0。
使用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()
答案 1 :(得分:1)
使用“工作人员池”处理您的数据。比每个 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()
答案 2 :(得分:0)
显然,没有人在等待你的例程完成。因此,程序在最后2个例程完成之前结束。在程序结束之前,您可以使用工作组等待所有的例行程序完成。这告诉它更好 - https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
答案 3 :(得分:0)
您可以在for循环中使用当前goroutine等待“子goroutines”
semLimit := 2
sem := make(chan struct{}, semLimit)
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)
}
// wait semaphore
for i := 0; i < semLimit; i++ {
wg<-struct{}{}
}
可选地,也可以用import sync
的经济性来编写一个简约的“信号量等待组”
semLimit := 2
// mini semaphored waitgroup
wg := make(chan struct{}, semLimit)
// mini methods
wgAdd := func(){ wg<-struct{}{} }
wgDone := func(){ <-wg }
wgWait := func(){ for i := 0; i < semLimit; i++ { wgAdd() } }
for _, i := range ints {
// acquire semaphore
wgAdd()
// start long running go routine
go func(id int, sem chan struct{}) {
// do something
// release semaphore
wgDone()
}(i, sem)
}
// wait semaphore
wgWait()
答案 4 :(得分:-1)
这是一个工作示例。最后的 app/packs/entrypoints/application.js
循环强制程序等待
直到工作完成:
<%= stylesheet_pack_tag "application" %>