对于我的要求之一,我必须创建N个工作程序例程,该例程将由一个监视程序监视。所有工作程序完成后,监视程序必须结束。我的代码以死锁结尾,请帮忙。
import "fmt" import "sync" import "strconv" 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) { defer wg.Done() for i:= range cs { fmt.Println(i) } } func main() { wg := &sync.WaitGroup{} cs := make(chan string) for i:=0;i<10;i++{ wg.Add(1) go worker(wg,cs,i) } wg.Add(1) go monitorWorker(wg,cs) wg.Wait() }
您的monitorWorker永不死。当所有工作人员完成时,它将继续等待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的第一条评论的答案。
您的程序包含三个需要同步的部分。首先,您所有的员工都需要发送数据。然后,您的打印循环需要打印该数据。然后,您的主要功能需要返回,从而结束程序。在您的示例中,所有工作程序都发送数据,所有数据都被打印,但是消息从未发送给main,它应该正常返回。
在我的示例中,main进行打印,而“ monitorWorker”仅告诉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 }