为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在并行处理时可以在 Go 中重用通道?

为什么在并行处理时可以在 Go 中重用通道?

Go
素胚勾勒不出你 2021-12-20 15:37:10
这是官方教程中的代码片段package mainimport "fmt"func sum(s []int, c chan int) {    sum := 0    for _, v := range s {        sum += v    }    c <- sum // send sum to c}func main() {    s := []int{7, 2, 8, -9, 4, 0}    c := make(chan int)    go sum(s[:len(s)/2], c)    go sum(s[len(s)/2:], c)    x, y := <-c, <-c // receive from c    fmt.Println(x, y, x+y)}既然我们是并行计算的,每个线程都把结果保存到同一个通道中,这不是把数据搞砸了吗?
查看完整描述

2 回答

?
慕标5832272

TA贡献1966条经验 获得超4个赞

通道操作是 goroutine 安全的。你可以在任何 goroutine 中读/写/关闭,而不会破坏任何进出通道的东西。基本上,通道是同步点。无缓冲通道(如您的情况)将在每次写入和读取时阻塞。当您编写代码时,您的代码会阻塞并等待有人开始在另一端阅读。当您阅读您的代码时,您的代码会阻塞并等待有人开始在另一端编写。

在您的情况下,goroutines 中的计算将同时完成(不需要并行),但会在通道写入时阻塞。您的主要 goroutine 将在第一次读取时阻塞,读取值。在第二次读取时阻塞,读取值。

即使您使用缓冲通道 - c := make(chan int, 2). 您的 goroutine 将完成计算,将结果写入通道而不阻塞并终止。什么都不会被破坏。与此同时,主 goroutine 将阻塞通道读取并等待有人写入它。

我建议你阅读Effective go , Go Concurrency Patterns并尝试A Tour of Go


查看完整回答
反对 回复 2021-12-20
?
长风秋雁

TA贡献1757条经验 获得超7个赞

确实,当您从两个不同的 goroutine 通过一个通道发送两个值时,不一定保证排序(除非您已经做了其他事情来协调它们的发送)。

但是,在此示例中,排序根本无关紧要。通道上正在发送两个值:前半部分的总和和第二部分的总和。

go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)

由于这两个值唯一用于计算总和,因此顺序根本无关紧要。事实上,如果您运行该示例的次数足够多,您应该会看到它x并且y经常被交换,但总和x+y始终相同。


查看完整回答
反对 回复 2021-12-20
  • 2 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信