为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕村225694 2021-11-01 16:24:14
下面是摘自“ Google I/O 2012 - Go Concurrency Patterns ”(幻灯片)的代码示例package mainimport (    "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 0Ann 0Joe 1Ann 1Joe 2Ann 2Joe 3Ann 3Joe 4Ann 4The end这是演讲者 Rob Pike 的解释(视频中的 16:33):“...我们正在读取 Joe 的值和 Ann 的值。而且由于频道的同步性质,两个人轮流进行,不仅打印出值,还执行它们。因为如果 Ann 准备发送值但 Joe 还没有这样做,Ann 仍然会被阻塞,等待将值传递给 main。 ”这让我很困惑。“如果 Ann 准备发送值但 Joe 还没有这样做,Ann 仍将被阻止”是什么意思?正如我们所知,通道在两个 goroutine 之间建立通信并同步它们的执行。但是我们在这里创建了两个频道(joe和ann)。主协程分别通过joe和与两个新的协程对话ann。这是否意味着通道之间的同步性质也有效?或者主 goroutine 一次只能与一个其他 goroutine 通信?
查看完整描述

3 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

这只是意味着这些通道是无缓冲的。

    fmt.Println(<-joe)
    fmt.Println(<-ann)

在第一行完成之前,第二行将无法执行。
第一个不会完成,直到有东西写入 joe 的频道。

如果该频道已有值,则 Ann 将无法在 Ann 的频道中写入。
并且在首先读取fmt.Println(<-ann)joe 的频道( ) 之前,不会读取该频道( fmt.Println(<-joe))。

两个通道都是独立的(彼此不知道),但读取操作的顺序性质使一个通道等待另一个首先被读取。


查看完整回答
反对 回复 2021-11-01
?
繁星coding

TA贡献1797条经验 获得超4个赞

当您说“一个通道在两个 goroutine 之间建立通信并同步它们的执行”时,您对情况的描述是错误的。

正在发生的同步在通道内。当您尝试从通道读取数据时,读取操作将被阻止,直到数据写入通道。

在这个例子中有两个不同的频道,他们中的任何一个都不知道另一个。重要的细节是此行阻塞,直到数据写入joe通道:

fmt.Println(<-joe)

这就是在打印“Joe”之前阻止执行以下行的原因


查看完整回答
反对 回复 2021-11-01
?
森林海

TA贡献2011条经验 获得超2个赞

通道是无缓冲的。

c := make(chan string)

容量(以元素数为单位)设置通道中缓冲区的大小。如果容量为零或不存在,则通道没有缓冲,只有当发送方和接收方都准备好时,通信才能成功。否则,如果缓冲区未满(发送)或非空(接收),则通道被缓冲并且通信成功而不会阻塞。一个 nil 通道永远不会准备好进行通信。

接收将按顺序,joe 其次是 ann。

fmt.Println(<-joe)
fmt.Println(<-ann)


查看完整回答
反对 回复 2021-11-01
  • 3 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信