Concurrency goroutines是如何工作的?

Concurrency goroutines是如何工作的?,concurrency,go,goroutine,Concurrency,Go,Goroutine,我一直在关注这一点,而当涉及到goroutines时,我有点被卡住了。我知道它们非常轻量级,每次一个goroutine阻塞时,另一个goroutine就会启动,但我无法理解这个示例实际上是如何工作的: package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { time.Sleep(1000 * time.Millisecond)

我一直在关注这一点,而当涉及到goroutines时,我有点被卡住了。我知道它们非常轻量级,每次一个goroutine阻塞时,另一个goroutine就会启动,但我无法理解这个示例实际上是如何工作的:

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(1000 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}
根据我对其他语言线程的有限理解,输出应该是这样的:

hello
world
world
world
world
world
world 
world
world
hello
world
world
或者像这样:

hello
world
world
world
world
world
world 
world
world
hello
world
world
为什么第二行执行五次呢?
go
语句下面的内容是否属于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)
}
主程序包
输入“fmt”
函数和(a[]整数,c chan整数){
总和:=0
对于u,v:=范围a{
总和+=v
}
C
为什么第二行也执行5次

第二行将在
main()
线程中每秒打印
hello

但同时,第一行“go say”(“world”)
也会在一个单独的goroutine中每秒钟打印五次world
Sleep
确保每一个例程都产生,允许另一个例程恢复

因此,输出:

hello
world
hello
world
hello
world
hello
world
hello

在我看来,sum函数将把它的和发送到通道c,然后下一个和将把它的和发送到相同的通道c,那么如何给这两个变量分配两个不同的值呢

因为每次发送都会在
c
上阻塞,直到读取频道
c

由于有两种写入
c
,因此您需要阅读:

 x, y := <-c, <-c // receive from c twice.

x,y:=对于第一个函数,你应该看到VonC样式中的值。之所以
hello
打印5次,也是因为函数
say
打印了5次。想象一下没有goroutine的程序。我想这并不能保证你每次都能得到
hello
world
完美地穿插,但我可能错了

该频道工作的原因是:

  • Golang让你做VonC提到的多项作业
  • 通道
    清空
    ,即当您将
    c
    分配给
    x
    时,它删除传递到通道中的第一个和,当它将
    c
    分配给
    y
    时,它传递第二个值(同样,我认为订单不是保证,因为
    x
    可以有上半部分和
    y
    下半部分的总和,反之亦然

  • 如果你把频道想象成一种队列,我认为这更有意义。求和goroutines将值推送到队列上,赋值按顺序弹出值。

    哦,我想我明白了。main本身就是一个go例程,正如你所说。hello会被打印出来,因为go例程中的睡眠阻塞了main。因为每当例程被阻止一个新的例程启动主函数重复5次,但同时函数本身也重复5次。首先打印Hello,因为代码跳过例程等待它休眠。这也是关于我的第二个示例的另一个问题。假设有数百万个使用go Prepend的和函数调用如果程序在求和完成计算之前没有到达阻塞程序的那一行,那么该值就会丢失,对吗?@Bula对迟来的回答表示抱歉。是的,main()本身就是一个goroutine,并且会在
    Sleep()上让步
    @Bula不,该值不会丢失:如果我理解正确,只要
    c,计算它的goroutine就会被阻塞在
    c上