Rob Pike对Go中"频道的同步特性"的意思是什么?

Pau*_*uli 3 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
}
Run Code Online (Sandbox Code Playgroud)

输出:

Joe 0
Ann 0
Joe 1
Ann 1
Joe 2
Ann 2
Joe 3
Ann 3
Joe 4
Ann 4
The end
Run Code Online (Sandbox Code Playgroud)

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

这困惑了我."如果安已经准备好发送一个价值,但乔还没有这样做,安仍会被封锁"是什么意思?众所周知,一个通道构建两个goroutine之间的通信并同步它们的执行.但是我们在这里(joeann)创建了两个频道.通过两个新够程主要的goroutine会谈joeann分别.这是否意味着同步性质在频道之间也有效?或者说主要的goroutine一次只能与另外一个goroutine交谈?

Von*_*onC 6

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

    fmt.Println(<-joe)
    fmt.Println(<-ann)
Run Code Online (Sandbox Code Playgroud)

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

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

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