这是官方教程中的代码片段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
长风秋雁
TA贡献1757条经验 获得超7个赞
确实,当您从两个不同的 goroutine 通过一个通道发送两个值时,不一定保证排序(除非您已经做了其他事情来协调它们的发送)。
但是,在此示例中,排序根本无关紧要。通道上正在发送两个值:前半部分的总和和第二部分的总和。
go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c)
由于这两个值唯一用于计算总和,因此顺序根本无关紧要。事实上,如果您运行该示例的次数足够多,您应该会看到它x
并且y
经常被交换,但总和x+y
始终相同。
- 2 回答
- 0 关注
- 163 浏览
添加回答
举报
0/150
提交
取消