goroutine out to channel channel fixed?

时间:2015-09-20 04:49:29

标签: go

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)
}

我让线程睡觉,但同样的事情发生了。我仍然很困惑。

1 个答案:

答案 0 :(得分:2)

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

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

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

据我所知,运行时选择的goroutine选择不是随机的。这与说它不是随机的不一样,但更不是假设是随机的。

重要的是,您的代码不应该关心计划goroutine的顺序。它是否总是像队列,向后(堆栈),或随机,或其他东西(可能是现实)。