package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[len(a)/2:], c)
go sum(a[:len(a)/2], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
x, y := <-c, <-c // receive from c
为什么这一行总会打印出相同的结果?
我认为应该有50/50的机会打印
17 -5 12
要么
-5 17 12
我认为两个例程应该是并行的
提前致谢!
package main
import "fmt"
import "time"
import "math/rand"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[len(a)/2:], c)
go sum(a[:len(a)/2], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
我让线程睡觉,但同样的事情发生了。我仍然很困惑。
答案 0 :(得分:2)
在这种情况下,假设 应该是50/50的机会是不正确的。要清楚,我并不是说它应该总是一个或另一个,而是你不应该期望每次程序运行时都要改变它。行为不一定是随机的(甚至是伪随机的)。
goroutine的保证不是它将在未来的随机时间安排,而是在未来的某个时间运行。如果调度程序的当前实现决定将goroutine放在一个简单的队列中,它就不会自动意味着它被破坏了。对于您的特定代码的情况,如果您在不同的地方贴上一些time.Sleep
或fmt.Printf
,您可能会看到订单有时会发生变化。
我想知道,当与频道一起使用时,你是否会混淆Go的调度程序对下一个goroutine的选择以及select
的记录伪随机行为。那里的行为被定义为随机的,并且说 的行为应该有50/50的机会是正确的。
据我所知,运行时选择的goroutine选择不是随机的。这与说它不是随机的不一样,但更不是假设是随机的。
重要的是,您的代码不应该关心计划goroutine的顺序。它是否总是像队列,向后(堆栈),或随机,或其他东西(可能是现实)。