package main
import "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)
}
由于我们并行进行计算,并且每个线程将其结果保存到同一个通道中,这不会搞砸数据吗?
答案 0 :(得分:0)
确实,当您通过两个不同的goroutine在一个频道上发送两个值时,订购不一定得到保证(除非您已经做了其他事情来协调他们的发送)。
然而,在这个例子中,排序并不重要。通道上发送了两个值:前半部分和第二部分之和。
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
由于这两个值的唯一用途是计算总和,因此订单根本不重要。实际上,如果您运行的示例足够多次,您应该会看到x
和y
经常被交换,但总和x+y
始终是相同的。
答案 1 :(得分:0)
渠道运营是安全的。您可以在任何goroutine中读取/写入/关闭,而不会破坏进出通道的任何内容。基本上,通道是同步点。无缓冲通道(如您的情况)将在每次写入和读取时阻塞。当你编写代码时会阻塞并等到有人开始阅读另一端。当你读到你的代码时会阻塞并等到有人开始写另一端。
在你的情况下,goroutine中的计算将同时完成(不需要并行),但会在通道写入时阻塞。您的主要goroutine将在第一次读取时阻止,读取值。阻止第二次读取,读取值。
即使您使用缓冲频道 - c := make(chan int, 2)
。您的goroutine将完成计算,将结果写入通道而不会阻塞并终止。什么都不会被破坏。与此同时,主要goroutine将阻止频道读取并等待有人写入它。