下面是摘自“ 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)
)。
两个通道都是独立的(彼此不知道),但读取操作的顺序性质使一个通道等待另一个首先被读取。
繁星coding
TA贡献1797条经验 获得超4个赞
当您说“一个通道在两个 goroutine 之间建立通信并同步它们的执行”时,您对情况的描述是错误的。
正在发生的同步在通道内。当您尝试从通道读取数据时,读取操作将被阻止,直到数据写入通道。
在这个例子中有两个不同的频道,他们中的任何一个都不知道另一个。重要的细节是此行阻塞,直到数据写入joe
通道:
fmt.Println(<-joe)
这就是在打印“Joe”之前阻止执行以下行的原因
森林海
TA贡献2011条经验 获得超2个赞
通道是无缓冲的。
c := make(chan string)
容量(以元素数为单位)设置通道中缓冲区的大小。如果容量为零或不存在,则通道没有缓冲,只有当发送方和接收方都准备好时,通信才能成功。否则,如果缓冲区未满(发送)或非空(接收),则通道被缓冲并且通信成功而不会阻塞。一个 nil 通道永远不会准备好进行通信。
接收将按顺序,joe 其次是 ann。
fmt.Println(<-joe) fmt.Println(<-ann)
- 3 回答
- 0 关注
- 194 浏览
添加回答
举报
0/150
提交
取消