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

goroutine 输出到通道顺序已修复?

goroutine 输出到通道顺序已修复?

Go
缥缈止盈 2021-11-08 16:46:53
package mainimport "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我觉得两个goroutine应该是并行的提前致谢!package mainimport "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)}我让线程进入睡眠状态,但同样的事情发生了。我还在纠结。
查看完整描述

1 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

在这种情况下,假设它应该是 50/50 的机会是不正确的。需要明确的是,我并不是建议它应该始终是一个或另一个,而是您不应该期望每次程序运行时它都会改变。该行为不一定是随机的(甚至是伪随机的)。

goroutine 的保证不是它会被安排在一个随机的未来时间,而是它会在未来的某个时间运行。如果调度器的当前实现决定将 goroutines 放在一个简单的队列中,它不会自动意味着它被破坏了。对于您的特定代码的情况,如果您在不同的地方粘贴几个time.Sleeps 或fmt.Printfs,您有时可能会看到顺序发生变化。

我想知道您是否将 Go 的调度程序对下一个 goroutine 的选择select与与通道一起使用时记录的伪随机行为混淆了。那里的行为被定义为随机的,正确地说行为应该有 50/50 的机会。

据我所知,运行时选择哪个 goroutine 并不是随机的。这不是说它不能是随机的,而是说它不应该是随机的。

重要的是你的代码不应该关心 goroutine 的调度顺序。无论它总是像队列一样有序,或向后(堆栈),或随机,或其他(可能是现实)。


查看完整回答
反对 回复 2021-11-08
  • 1 回答
  • 0 关注
  • 157 浏览
慕课专栏
更多

添加回答

举报

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