Golang`select`似乎不公平

kem*_*iya 4 concurrency go

我是Golang的初学者,我从选择的官方规范中读到,当更多的通信可以继续进行时,我会做统一的伪随机,但是当我尝试下面的代码时

package main

import (
    "fmt"
)

func main() {

    // For our example we'll select across two channels.
    c1 := make(chan string)
    c2 := make(chan string)

    go func() {
        for {
            c1 <- "one"
        }
    }()
    go func() {
        for {
            c2 <- "two"
        }
    }()

    for i := 0; i < 100; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它总是打印'收到两个',似乎不是随机的结果,所以我错在哪里?

代码可以在这里测试.

Fen*_*iko 5

问题是你在go playground上运行它,在Go Playground上,GOMAXPROCS是1,这意味着一次执行一个goroutine,如果goroutine没有阻塞,调度程序不会被迫切换到其他goroutine.

因此,您应该在本地计算机上运行它,以查看实际结果

当您在本地运行时,很可能GOMAXPROCS将大于1,因为它默认为可用的CPU核心数(自Go 1.5起).所以如果你有一个goroutine执行一个无限循环没关系,另一个goroutine将同时执行,这将是main(),当main()返回时,你的程序终止; 它不等待其他非主要的goroutines完成

  • 我在我的本地机器上试过它,它确实显示了随机结果.但是我对这个解释感到有些困惑,GOMAXPROCS实际上是Go Playground上的1,但是调度程序应该总是在主goroutine和其他goroutine之间切换,因为`c1`和`c2`都没有缓冲,不是吗?当一条消息发送到频道时,它应该阻止很短的时间,所以主要的goroutine可以接收它,但为什么它不能切换到另一个发送器goroutine? (2认同)