go语言里面关于channel和select的问题

我有段代码是启动了一个goroutine,在一个无限循环中给一个channel数组中一个随机元素赋值,主线程使用select从中取值,但是通过打印我发现,goroutine执行两次循环后,切换到主线程,,特别有规律,这是为什么?这种切换不是cpu随机的吗?怎么会有这种规律性?(可以看x和y的打印结果)
代码如下:
package main

import (

"math/rand"
"fmt"
"time"

)

func main() {

rand.Seed(time.Now().UTC().UnixNano())
channels := make([]chan bool, 6)
for i := range channels {
    channels[i] = make(chan bool)
}
go func() {
    for {
        y := rand.Intn(6)

        fmt.Printf("y:%d\n", y)
        channels[y] <- true

    }
}()
for i := 0; i < 36; i++ {
    var x int
    select {
    case <-channels[0]:
        x = 1
    case <-channels[1]:
        x = 2
    case <-channels[2]:
        x = 3
    case <-channels[3]:
        x = 4
    case <-channels[4]:
        x = 5
    case <-channels[5]:
        x = 6
    }
    fmt.Printf("x:%d\n", x)
}
fmt.Println()

}
输出结果:
y:2
y:2
x:3
x:3
y:1
y:2
x:2
x:3
y:0
y:2
x:1
x:3
y:1
y:2
x:2
x:3
y:1
y:5
x:2
x:6
y:0
y:1
x:1
x:2
y:4
y:5
x:5
x:6
y:1
y:4
x:2
x:5
y:0
y:5
x:1
x:6
y:5
y:1
x:6
x:2
y:2
y:0
x:3
x:1
y:3
y:3
x:4
x:4
y:1
y:2
x:2
x:3
y:1
y:3
x:2
x:4
y:5
y:2
x:6
x:3
y:4
y:0
x:5
x:1
y:2
y:1
x:3
x:2
y:4
y:1
x:5
x:2

Process finished with exit code 0

阅读 3k
3 个回答

cpu 和 goroutine 默认情况下并不是 1:1 的关系,对各个 goroutine 的调度是 go runtime 的调度器决定的

因为你用的阻塞模式, 两个协程形成互相依赖.

发送方 channels[y] <- true 被阻塞, 直到接收方 case <-channels[x]: 接收了, 反向亦然.

你可以设置 channel 缓存观察不一样的结果, 示例如下

package main
import (
    "fmt"
    "math/rand"
    "time"
)
func main() {
    rand.Seed(time.Now().UTC().UnixNano())
    channels := make([]chan bool, 6)
    for i := range channels {
        channels[i] = make(chan bool, 6)
    }
    go func() {
        for i := 0; i < 36; i++ {
            y := rand.Intn(6)
            fmt.Printf("y:%d\n", y)
            channels[y] <- true
        }
    }()
    for i := 0; i < 36; i++ {
        var x int
        select {
        case <-channels[0]:
            x = 1
        case <-channels[1]:
            x = 2
        case <-channels[2]:
            x = 3
        case <-channels[3]:
            x = 4
        case <-channels[4]:
            x = 5
        case <-channels[5]:
            x = 6
        }
        fmt.Printf("x:%d\n", x)
    }
    fmt.Println()
}

这种情况可能是两个goroutine并行执行

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题