猿问

如何关闭多个 goroutine 正在发送的通道?

我正在尝试并行进行一些计算。该程序的设计使得每个工作程序 goroutine 将已解决难题的“碎片”发送回控制器 goroutine,后者等待接收并组装从工作程序发送的所有内容。

关闭单通道的 idomatic Go 是什么?我无法在每个 goroutine 中的通道上调用 close,因为那样我可能会在关闭的通道上发送。同样,无法预先确定哪个 goroutine 将首先完成。这里需要 sync.WaitGroup 吗?


幕布斯7119047
浏览 212回答 2
2回答

叮当猫咪

这是一个使用sync.WaitGroup来做你正在寻找的事情的例子,这个例子接受一个很长的整数列表,然后通过向 N 个并行工作人员处理一个相等大小的输入数据块来将它们全部相加。它可以在go playground上运行:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync")const WorkerCount = 10func main() {&nbsp; &nbsp; // Some input data to operate on.&nbsp; &nbsp; // Each worker gets an equal share to work on.&nbsp; &nbsp; data := make([]int, WorkerCount*10)&nbsp; &nbsp; for i := range data {&nbsp; &nbsp; &nbsp; &nbsp; data[i] = i&nbsp; &nbsp; }&nbsp; &nbsp; // Sum all the entries.&nbsp; &nbsp; result := sum(data)&nbsp; &nbsp; fmt.Printf("Sum: %d\n", result)}// sum adds up the numbers in the given list, by having the operation delegated// to workers operating in parallel on sub-slices of the input data.func sum(data []int) int {&nbsp; &nbsp; var sum int&nbsp; &nbsp; result := make(chan int)&nbsp; &nbsp; defer close(result)&nbsp; &nbsp; // Accumulate results from workers.&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case value := <-result:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum += value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()&nbsp; &nbsp; // The WaitGroup will track completion of all our workers.&nbsp; &nbsp; wg := new(sync.WaitGroup)&nbsp; &nbsp; wg.Add(WorkerCount)&nbsp; &nbsp; // Divide the work up over the number of workers.&nbsp; &nbsp; chunkSize := len(data) / WorkerCount&nbsp; &nbsp; // Spawn workers.&nbsp; &nbsp; for i := 0; i < WorkerCount; i++ {&nbsp; &nbsp; &nbsp; &nbsp; go func(i int) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset := i * chunkSize&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; worker(result, data[offset:offset+chunkSize])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; }(i)&nbsp; &nbsp; }&nbsp; &nbsp; // Wait for all workers to finish, before returning the result.&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; return sum}// worker sums up the numbers in the given list.func worker(result chan int, data []int) {&nbsp; &nbsp; var sum int&nbsp; &nbsp; for _, v := range data {&nbsp; &nbsp; &nbsp; &nbsp; sum += v&nbsp; &nbsp; }&nbsp; &nbsp; result <- sum}

哔哔one

是的,这是 sync.WaitGroup 的完美用例。您的另一种选择是每个 goroutine 使用 1 个通道,并使用一个多路复用器 goroutine,从每个通道输入单个通道。但这会很快变得笨拙,所以我只需要一个sync.WaitGroup。
随时随地看视频慕课网APP

相关分类

Go
我要回答