你的班长永远不会死.当所有工人完成后,它继续等待cs.这是死锁的,因为没有其他的东西会在CS上发送,因此WG永远不会达到0.一种可能的解决方法是让监视器在所有工作人员完成时关闭通道.如果for循环在Main中,它将结束循环,从Main返回,然后结束程序.
例如:http://play.golang.org/p/nai7XtTMfr
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
for i := range cs {
fmt.Println(i)
}
}
这是对OP的第一条 comments 的回答.
您的程序有三个部分需要同步.首先,所有员工都需要发送数据.然后打印循环需要打印这些数据.然后主函数需要返回,从而结束程序.在您的示例中,所有的工作人员都会发送数据,所有的数据都会被打印出来,但消息永远不会发送到main,它应该优雅地返回.
在我的示例中,main执行打印,"monitor orWorker"只在收到需要打印的所有数据时告诉main.这样,程序就可以优雅地结束,而不会死锁.
如果您坚持将打印循环放在另一个Goroutine中,您可以这样做.但随后需要将额外的通信发送到Main,这样它才能返回.在下一个示例中,我使用通道来确保打印所有数据时的主端.
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func printWorker(cs <-chan string, done chan<- bool) {
for i := range cs {
fmt.Println(i)
}
done <- true
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
done := make(chan bool, 1)
go printWorker(cs, done)
<-done
}