【发布时间】:2014-08-27 06:29:07
【问题描述】:
我正在尝试遵循http://blog.golang.org/pipelines/bounded.go 上发布的有界 goroutine 示例。我遇到的问题是,如果增加的工人数量超过了要做的工作量,那么额外的工人永远不会被取消。其他一切似乎都正常工作,值被计算和记录,但是当我关闭groups 频道时,工作人员只是挂在范围语句上。
我想我不明白(在我的代码和示例代码中)是工人如何知道没有更多工作要做并且他们应该退出?
更新
一个工作(即非工作)示例发布在http://play.golang.org/p/T7zBCYLECp。它显示了工人的僵局,因为他们都睡着了,没有工作要做。我感到困惑的是,我认为示例代码会有同样的问题。
这是我目前正在使用的代码:
// Creates a pool of workers to do a bunch of computations
func computeAll() error {
done := make(chan struct{})
defer close(done)
groups, errc := findGroups(done)
// start a fixed number of goroutines to schedule with
const numComputers = 20
c := make(chan result)
var wg sync.WaitGroup
wg.Add(numComputers)
for i := 0; i < numComputers; i++ {
go func() {
compute(done, groups, c)
wg.Done()
}()
}
go func() {
wg.Wait()
close(c)
}()
// log the results of the computation
for r := range c { // log the results }
if err := <-errc; err != nil {
return err
}
return nil
}
这是用数据填充通道的代码:
// Retrieves the groups of data the must be computed
func findGroups(done <-chan struct{}) (<-chan model, <-chan error) {
groups := make(chan model)
errc := make(chan error, 1)
go func() {
// close the groups channel after find returns
defer close(groups)
group, err := //... code to get the group ...
if err == nil {
// add the group to the channel
select {
case groups <- group:
}
}
}()
return groups, errc
}
这是读取通道进行计算的代码。
// Computes the results for the groups of data
func compute(done <-chan struct{}, groups <-chan model, c chan<- result) {
for group := range groups {
value := compute(group)
select {
case c <- result{value}:
case <-done:
return
}
}
}
【问题讨论】:
-
找到这类事情的一个好方法是尝试使用 -race 运行它
-
-race 没有产生任何不同。 goroutines 被创建,所有的工作都完成了,然后它不会退出,因为一些 goroutines 还活着。
-
你能发布一个可运行代码的要点吗?
-
我在play.golang.org/p/T7zBCYLECp 创建了一个示例。看起来有死锁,但我不知道如何解决它。
-
你为什么把
groups <- group写成select { case groups <- group: }?
标签: parallel-processing go goroutine