猿问

Rob Pike 在 Go 中所说的“通道的同步特性”是什么意思?

下面是摘自“ Google I/O 2012 - Go Concurrency Patterns ”(幻灯片)的代码示例


package main


import (

    "fmt"

    "time"

)


func main() {

    joe := boring("Joe")

    ann := boring("Ann")

    for i := 0; i < 5; i++ {

        fmt.Println(<-joe)

        fmt.Println(<-ann)

    }

    fmt.Println("The end")

}


func boring(msg string) <-chan string {

    c := make(chan string)

    go func() {

        for i := 0; ; i++ {

            c <- fmt.Sprintf("%s %d", msg, i)

            time.Sleep(time.Second)

        }

    }()

    return c

}

输出:


Joe 0

Ann 0

Joe 1

Ann 1

Joe 2

Ann 2

Joe 3

Ann 3

Joe 4

Ann 4

The end

这是演讲者 Rob Pike 的解释(视频中的 16:33):“...我们正在读取 Joe 的值和 Ann 的值。而且由于频道的同步性质,两个人轮流进行,不仅打印出值,还执行它们。因为如果 Ann 准备发送值但 Joe 还没有这样做,Ann 仍然会被阻塞,等待将值传递给 main。 ”


这让我很困惑。“如果 Ann 准备发送值但 Joe 还没有这样做,Ann 仍将被阻止”是什么意思?正如我们所知,通道在两个 goroutine 之间建立通信并同步它们的执行。但是我们在这里创建了两个频道(joe和ann)。主协程分别通过joe和与两个新的协程对话ann。这是否意味着通道之间的同步性质也有效?或者主 goroutine 一次只能与一个其他 goroutine 通信?


慕村225694
浏览 195回答 3
3回答

哔哔one

这只是意味着这些通道是无缓冲的。    fmt.Println(<-joe)     fmt.Println(<-ann)在第一行完成之前,第二行将无法执行。第一个不会完成,直到有东西写入 joe 的频道。如果该频道已有值,则 Ann 将无法在 Ann 的频道中写入。并且在首先读取fmt.Println(<-ann)joe 的频道( ) 之前,不会读取该频道( fmt.Println(<-joe))。两个通道都是独立的(彼此不知道),但读取操作的顺序性质使一个通道等待另一个首先被读取。

繁星coding

当您说“一个通道在两个 goroutine 之间建立通信并同步它们的执行”时,您对情况的描述是错误的。正在发生的同步在通道内。当您尝试从通道读取数据时,读取操作将被阻止,直到数据写入通道。在这个例子中有两个不同的频道,他们中的任何一个都不知道另一个。重要的细节是此行阻塞,直到数据写入joe通道:fmt.Println(<-joe)这就是在打印“Joe”之前阻止执行以下行的原因

森林海

通道是无缓冲的。c&nbsp;:=&nbsp;make(chan&nbsp;string)容量(以元素数为单位)设置通道中缓冲区的大小。如果容量为零或不存在,则通道没有缓冲,只有当发送方和接收方都准备好时,通信才能成功。否则,如果缓冲区未满(发送)或非空(接收),则通道被缓冲并且通信成功而不会阻塞。一个 nil 通道永远不会准备好进行通信。接收将按顺序,joe 其次是 ann。fmt.Println(<-joe) fmt.Println(<-ann)
随时随地看视频慕课网APP

相关分类

Go
我要回答