go - 为什么 goroutines 用缓冲通道解决死锁问题?
问题描述
我有一个缓冲通道,我故意限制为 2 个元素。当我将更多元素写入通道而不从中读取时,我会按预期出现死锁。但是,如果我使用 goroutine 写入我的频道,问题就消失了。为什么?
// Function to process messages in an array. We stop processing once we
// encounter the string 'stop' even if there are other messages
func processCmd(s []string, c chan int) {
msgCount := 0
for index, v := range s {
if index == len(s)-1 && v == "stop" {
// If we've reached the last element and the message is "stop", don't count it
break
} else if v == "stop" {
c <- msgCount // Send msgCount to the channel
continue
} else {
msgCount++
}
}
c <- msgCount // Send msgCount to the channel
close(c)
}
func main() {
s := []string{"message a", "message b", "message c", "stop", "message d", "stop", "message e"}
c := make(chan int, 2)
processCmd(s, c)
//go processCmd(s, c) // doesn't have an issue with buffer length
for v := range c {
fmt.Println(v)
}
}
解决方案
内联运行时processCmd
(如代码所示),没有从通道接收任何内容。一旦添加了两个元素,processCmd
就会等到有空间添加更多元素。正如您所说,这按预期工作。
在 goroutine 中运行processCmd
时,main()
启动 goroutine 并进入for v := range c
循环。这将消耗项目,c
直到通道关闭。一旦v := range c
消耗了第一个元素,processCmd
就可以自由地向通道添加更多数据,从而解除阻塞。
这将一直持续到processCmd
关闭通道,此时 for 循环将终止,程序也将终止。
注意:为了可见性,不要忘记添加go
标签。goroutine
看标签的人不多。
推荐阅读
- angular - 测试用例在全局角度单元测试中随机失败
- visual-c++ - 在 VEGAS Pro 中调试 OpenFX 插件
- unity3d - Unity 脚本中的事件类型
- excel - 根据给定条件的总和范围从一列返回值
- web-services - Integration springboot web service into html/bootstrap form
- python - Python 多处理:如何在服务器启动时创建进程,并在调用 API 端点时使用它们?
- swift - 无法在 Swift (UIKIT) 中生成本地通知
- c# - 无法使用实体框架核心映射实体
- amazon-s3 - 我想知道,如何通过指定一些分支从多分支编写 Jenkinsfile
- c# - 为什么等待之前的异常不会在没有等待的情况下抛出?