Concurrency Go并发和通道混乱

Concurrency Go并发和通道混乱,concurrency,go,channel,goroutine,Concurrency,Go,Channel,Goroutine,我是新手,在理解并发性和通道方面有问题 package main import "fmt" func display(msg string, c chan bool){ fmt.Println("display first message:", msg) c <- true } func sum(c chan bool){ sum := 0 for i:=0; i < 10000000000; i++ { sum++ }

我是新手,在理解并发性和通道方面有问题

package main

import "fmt"

func display(msg string, c chan bool){
    fmt.Println("display first message:", msg)
    c <- true
}

func sum(c chan bool){
    sum := 0
    for i:=0; i < 10000000000; i++ {
        sum++
    }
    fmt.Println(sum)
    c <- true
}

func main(){
    c := make(chan bool)

    go display("hello", c)
    go sum(c)
    <-c
}
但我认为应该只有一行:

display first message: hello

因此,在main函数中,程序的确切输出没有定义,取决于调度器。调度器可以在当前未被阻止的所有goroutine之间自由选择。它试图通过在很短的时间间隔内切换当前goroutine来同时运行这些goroutine,这样用户就会感觉到所有事情都是同时发生的。除此之外,它还可以在不同的CPU上并行执行多个goroutine(如果您碰巧有一个多核系统并增加了内存)。可能导致输出的一种情况是:

  • main
    创建两个goroutine
  • 调度程序选择立即切换到一个新的goroutine并选择
    display

  • display
    打印出消息,并被发送频道阻止(
    c正如tux21b所建议的,这可能是因为
    runtime.GOMAXPROCS
    。将其放大,您可能会看到不同。感谢您的澄清。在步骤3中,由于没有接收器,显示被通道发送阻止。呃……接收器何时准备就绪?通道是同步的,这意味着接收器和发送器都是同步的必须准备好传输值。如果goroutine执行
    c,只需一条注释。据我所知,当前版本中的Go调度程序不是抢占式的。一旦goroutine拥有CPU,它将不会切换到另一个,直到它被阻止(由于I/O、通道、互斥等原因)。因此,如果先执行sum,它将独占使用CPU,直到被通道阻塞为止(我不确定fmt.Println是否会产生CPU开关)。我了解到,Go 1.2计划使用抢占式调度程序。当然,如果GOMAXPROCS不是1,另一个goroutine将使用另一个So级别的进程,并将由So调度。更多信息如下:
    
    display first message: hello