猿问

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

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


我觉得两个goroutine应该是并行的


提前致谢!


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)

}

我让线程进入睡眠状态,但同样的事情发生了。我还在纠结。


缥缈止盈
浏览 158回答 1
1回答

狐的传说

在这种情况下,假设它应该是 50/50 的机会是不正确的。需要明确的是,我并不是建议它应该始终是一个或另一个,而是您不应该期望每次程序运行时它都会改变。该行为不一定是随机的(甚至是伪随机的)。goroutine 的保证不是它会被安排在一个随机的未来时间,而是它会在未来的某个时间运行。如果调度器的当前实现决定将 goroutines 放在一个简单的队列中,它不会自动意味着它被破坏了。对于您的特定代码的情况,如果您在不同的地方粘贴几个time.Sleeps 或fmt.Printfs,您有时可能会看到顺序发生变化。我想知道您是否将 Go 的调度程序对下一个 goroutine 的选择select与与通道一起使用时记录的伪随机行为混淆了。那里的行为被定义为随机的,正确地说行为应该有 50/50 的机会。据我所知,运行时选择哪个 goroutine 并不是随机的。这不是说它不能是随机的,而是说它不应该是随机的。重要的是你的代码不应该关心 goroutine 的调度顺序。无论它总是像队列一样有序,或向后(堆栈),或随机,或其他(可能是现实)。
随时随地看视频慕课网APP

相关分类

Go
我要回答